4 * Read the binary dump of a Repo and create a Repo * from it
7 * Repo *pool_addrepo_solv(Pool *pool, FILE *fp)
19 #include "repo_solv.h"
22 #define INTERESTED_START 2
23 #define INTERESTED_END 13
25 /*-----------------------------------------------------------------*/
26 /* .solv read functions */
38 for (i = 0; i < 4; i++)
43 fprintf(stderr, "unexpected EOF\n");
63 fprintf(stderr, "unexpected EOF\n");
75 read_id(FILE *fp, Id max)
80 for (i = 0; i < 5; i++)
85 fprintf(stderr, "unexpected EOF\n");
93 fprintf(stderr, "read_id: id too large (%u/%u)\n", x, max);
98 x = (x << 7) ^ c ^ 128;
100 fprintf(stderr, "read_id: id too long\n");
110 read_idarray(FILE *fp, Id max, Id *map, Id *store, Id *end)
119 fprintf(stderr, "unexpected EOF\n");
124 x = (x << 6) | (c & 63);
127 fprintf(stderr, "read_idarray: id too large (%u/%u)\n", x, max);
132 fprintf(stderr, "read_idarray: array overflow\n");
140 fprintf(stderr, "read_idarray: array overflow\n");
149 x = (x << 7) ^ c ^ 128;
154 /*-----------------------------------------------------------------*/
156 typedef struct solvdata {
163 // ----------------------------------------------
166 * read repo from .solv file
171 pool_addrepo_solv(Pool *pool, FILE *fp, const char *reponame)
174 unsigned int numid, numrel, numsolv, numsrcdata, numsolvdata;
175 int numsolvdatabits, type;
177 Offset *str; /* map Id -> Offset into string space */
178 char *strsp; /* repo string space */
179 char *sp; /* pointer into string space */
180 Id *idmap; /* map of repo Ids to pool Ids */
182 unsigned int hashmask, h;
189 unsigned int size, size_str, size_idarray;
191 Id *idarraydatap, *idarraydataend;
193 unsigned int databits;
196 if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
198 fprintf(stderr, "not a SOLV file\n");
201 if (read_u32(fp) != SOLV_VERSION)
203 fprintf(stderr, "unsupported SOLV version\n");
207 /* create empty Repo */
208 repo = pool_addrepo_empty(pool);
209 pool_freeidhashes(pool);
211 repo->name = reponame;
213 numid = read_u32(fp);
214 numrel = read_u32(fp);
215 numsolv= read_u32(fp);
217 sizeid = read_u32(fp); /* size of string+Id space */
220 * read strings and Ids
228 /* alloc string buffer */
229 strsp = (char *)xrealloc(pool->stringspace, pool->sstrings + sizeid + 1);
230 /* alloc string offsets (Id -> Offset into string space) */
231 str = (Offset *)xrealloc(pool->strings, (pool->nstrings + numid) * sizeof(Offset));
233 pool->stringspace = strsp;
234 pool->strings = str; /* array of offsets into strsp, indexed by Id */
236 /* point to _BEHIND_ already allocated string/Id space */
237 strsp += pool->sstrings;
239 /* alloc id map for name and rel Ids */
240 idmap = (Id *)xcalloc(numid + numrel, sizeof(Id));
243 * read new repo at end of pool
246 if (fread(strsp, sizeid, 1, fp) != 1)
248 fprintf(stderr, "read error while reading strings\n");
251 strsp[sizeid] = 0; /* make string space \0 terminated */
255 * build hashes for all read strings
259 hashmask = mkmask(pool->nstrings + numid);
262 printf("read %d strings\n", numid);
263 printf("string hash buckets: %d\n", hashmask + 1);
267 * ensure sufficient hash size
270 hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
273 * fill hashtable with strings already in pool
276 for (i = 1; i < pool->nstrings; i++) /* leave out our dummy zero id */
278 h = strhash(pool->stringspace + pool->strings[i]) & hashmask;
279 hh = HASHCHAIN_START;
281 h = HASHCHAIN_NEXT(h, hh, hashmask);
286 * run over string space, calculate offsets
288 * build id map (maps solv Id -> pool Id)
291 for (i = 1; i < numid; i++)
293 if (sp >= strsp + sizeid)
295 fprintf(stderr, "not enough strings\n");
298 if (!*sp) /* empty string */
306 h = strhash(sp) & hashmask;
307 hh = HASHCHAIN_START;
313 if (!strcmp(pool->stringspace + pool->strings[id], sp))
314 break; /* existing string */
315 h = HASHCHAIN_NEXT(h, hh, hashmask);
318 /* length == offset to next string */
320 if (id == ID_NULL) /* end of hash chain -> new string */
322 id = pool->nstrings++;
324 str[id] = pool->sstrings; /* save Offset */
325 if (sp != pool->stringspace + pool->sstrings) /* not at end-of-buffer */
326 memmove(pool->stringspace + pool->sstrings, sp, l); /* append to pool buffer */
329 idmap[i] = id; /* repo relative -> pool relative */
330 sp += l; /* next string */
333 pool_shrink_strings(pool); /* vacuum */
344 ran = (Reldep *)xrealloc(pool->rels, (pool->nrels + numrel) * sizeof(Reldep));
347 fprintf(stderr, "no mem for rel space\n");
350 pool->rels = ran; /* extended rel space */
352 hashmask = mkmask(pool->nrels + numrel);
354 printf("read %d rels\n", numrel);
355 printf("rel hash buckets: %d\n", hashmask + 1);
358 * prep hash table with already existing RelDeps
361 hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
362 for (i = 1; i < pool->nrels; i++)
364 h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
365 hh = HASHCHAIN_START;
367 h = HASHCHAIN_NEXT(h, hh, hashmask);
372 * read RelDeps from repo
375 for (i = 0; i < numrel; i++)
377 name = read_id(fp, i + numid); /* read (repo relative) Ids */
378 evr = read_id(fp, i + numid);
380 name = idmap[name]; /* map to (pool relative) Ids */
382 h = relhash(name, evr, flags) & hashmask;
383 hh = HASHCHAIN_START;
387 if (id == ID_NULL) /* end of hash chain */
389 if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
391 h = HASHCHAIN_NEXT(h, hh, hashmask);
393 if (id == ID_NULL) /* new RelDep */
399 ran[id].flags = flags;
401 idmap[i + numid] = MAKERELDEP(id); /* fill Id map */
404 pool_shrink_rels(pool); /* vacuum */
408 * read (but dont store) repo data
412 printf("read repo data\n");
414 numsrcdata = read_u32(fp);
415 for (i = 0; i < numsrcdata; i++)
418 id = idmap[read_id(fp, numid)];
422 read_id(fp, numid + numrel); /* just check Id */
428 while(read_u8(fp) != 0)
432 fprintf(stderr, "unknown type\n");
443 printf("read solvable data info\n");
445 numsolvdata = read_u32(fp);
447 solvdata = (SolvData *)xmalloc(numsolvdata * sizeof(SolvData));
451 for (i = 0; i < numsolvdata; i++)
454 solvdata[i].type = type;
455 if ((type & TYPE_BITMAP) != 0)
460 id = idmap[read_id(fp, numid)];
462 printf("#%d: %s\n", i, id2str(pool, id));
466 solvdata[i].size = size;
467 if (id >= INTERESTED_START && id <= INTERESTED_END)
469 if (type == TYPE_STR)
471 if (type == TYPE_IDARRAY)
472 size_idarray += size;
476 if (numsolvdatabits >= 32)
478 fprintf(stderr, "too many data map bits\n");
483 size_idarray++; /* first entry is always zero */
484 repo->idarraydata = (Id *)xmalloc(sizeof(Id) * size_idarray);
485 repo->idarraysize = size_idarray;
486 idarraydatap = repo->idarraydata;
488 idarraydataend = repo->idarraydata + size_idarray;
492 repo->idarraydata = 0;
493 repo->idarraysize = 0;
498 /* alloc solvables */
499 pool->solvables = (Solvable *)xrealloc(pool->solvables, (pool->nsolvables + numsolv) * sizeof(Solvable));
501 if (numsolv) /* clear newly allocated area */
502 memset(pool->solvables + pool->nsolvables, 0, numsolv * sizeof(Solvable));
503 repo->start = pool->nsolvables;
504 repo->nsolvables = numsolv;
511 printf("read solvables\n");
513 for (i = 0, s = pool->solvables + repo->start; i < numsolv; i++, s++)
519 for (j = 0; j < (numsolvdatabits + 7) >> 3; j++)
520 databits = (databits << 8) | read_u8(fp);
522 for (j = 0; j < numsolvdata; j++)
524 type = solvdata[j].type;
525 if ((type & TYPE_BITMAP) != 0)
539 did = idmap[read_id(fp, numid + numrel)];
540 if (id == SOLVABLE_NAME)
542 else if (id == SOLVABLE_ARCH)
544 else if (id == SOLVABLE_EVR)
547 printf("%s -> %s\n", id2str(pool, id), id2str(pool, did));
553 printf("%s -> %u\n", id2str(pool, id), h);
555 if (id == RPM_RPMDBID)
558 repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
559 repo->rpmdbid[i] = h;
563 while(read_u8(fp) != 0)
567 if (id < INTERESTED_START || id > INTERESTED_END)
569 /* not interested in array */
570 while ((read_u8(fp) & 0xc0) != 0)
574 ido = idarraydatap - repo->idarraydata;
575 idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend);
576 if (id == SOLVABLE_PROVIDES)
578 else if (id == SOLVABLE_OBSOLETES)
580 else if (id == SOLVABLE_CONFLICTS)
582 else if (id == SOLVABLE_REQUIRES)
584 else if (id == SOLVABLE_RECOMMENDS)
586 else if (id == SOLVABLE_SUPPLEMENTS)
587 s->supplements = ido;
588 else if (id == SOLVABLE_SUGGESTS)
590 else if (id == SOLVABLE_ENHANCES)
592 else if (id == SOLVABLE_FRESHENS)
595 printf("%s ->\n", id2str(pool, id));
596 for (; repo->idarraydata[ido]; ido++)
597 printf(" %s\n", dep2str(pool, repo->idarraydata[ido]));
607 pool->nsolvables += numsolv;