Pfeww. I'm tired, but now you can add refers from repo SOLV files to
[platform/upstream/libsolv.git] / src / repo_solv.c
1 /*
2  * Copyright (c) 2007, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * repo_solv.c
10  * 
11  * Read the binary dump of a Repo and create a Repo * from it
12  * 
13  *  See
14  *   Repo *pool_addrepo_solv(Pool *pool, FILE *fp)
15  * below
16  * 
17  */
18
19
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25
26 #include "repo_solv.h"
27 #include "util.h"
28 #include "attr_store_p.h"
29
30 #define INTERESTED_START        SOLVABLE_NAME
31 #define INTERESTED_END          SOLVABLE_FRESHENS
32
33 static Pool *mypool;            /* for pool_debug... */
34
35 /*-----------------------------------------------------------------*/
36 /* .solv read functions */
37
38 /*
39  * read u32
40  */
41
42 static unsigned int
43 read_u32(FILE *fp)
44 {
45   int c, i;
46   unsigned int x = 0;
47
48   for (i = 0; i < 4; i++)
49     {
50       c = getc(fp);
51       if (c == EOF)
52         {
53           pool_debug(mypool, SAT_FATAL, "unexpected EOF\n");
54           exit(1);
55         }
56       x = (x << 8) | c;
57     }
58   return x;
59 }
60
61
62 /*
63  * read u8
64  */
65
66 static unsigned int
67 read_u8(FILE *fp)
68 {
69   int c;
70   c = getc(fp);
71   if (c == EOF)
72     {
73       pool_debug(mypool, SAT_FATAL, "unexpected EOF\n");
74       exit(1);
75     }
76   return c;
77 }
78
79
80 /*
81  * read Id
82  */
83
84 static Id
85 read_id(FILE *fp, Id max)
86 {
87   unsigned int x = 0;
88   int c, i;
89
90   for (i = 0; i < 5; i++)
91     {
92       c = getc(fp);
93       if (c == EOF)
94         {
95           pool_debug(mypool, SAT_FATAL, "unexpected EOF\n");
96           exit(1);
97         }
98       if (!(c & 128))
99         {
100           x = (x << 7) | c;
101           if (max && x >= max)
102             {
103               pool_debug(mypool, SAT_FATAL, "read_id: id too large (%u/%u)\n", x, max);
104               exit(1);
105             }
106           return x;
107         }
108       x = (x << 7) ^ c ^ 128;
109     }
110   pool_debug(mypool, SAT_FATAL, "read_id: id too long\n");
111   exit(1);
112 }
113
114
115 /*
116  * read array of Ids
117  */
118
119 static Id *
120 read_idarray(FILE *fp, Id max, Id *map, Id *store, Id *end, int relative)
121 {
122   unsigned int x = 0;
123   int c;
124   Id old = 0;
125   for (;;)
126     {
127       c = getc(fp);
128       if (c == EOF)
129         {
130           pool_debug(mypool, SAT_FATAL, "unexpected EOF\n");
131           exit(1);
132         }
133       if ((c & 128) == 0)
134         {
135           x = (x << 6) | (c & 63);
136           if (relative)
137             {
138               if (x == 0 && c == 0x40)
139                 {
140                   /* prereq hack */
141                   if (store == end)
142                     {
143                       pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
144                       exit(1);
145                     }
146                   *store++ = SOLVABLE_PREREQMARKER;
147                   old = 0;
148                   x = 0;
149                   continue;
150                 }
151               x = (x - 1) + old;
152               old = x;
153             }
154           if (x >= max)
155             {
156               pool_debug(mypool, SAT_FATAL, "read_idarray: id too large (%u/%u)\n", x, max);
157               exit(1);
158             }
159           if (map)
160             x = map[x];
161           if (store == end)
162             {
163               pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
164               exit(1);
165             }
166           *store++ = x;
167           if ((c & 64) == 0)
168             {
169               if (x == 0)       /* already have trailing zero? */
170                 return store;
171               if (store == end)
172                 {
173                   pool_debug(mypool, SAT_FATAL, "read_idarray: array overflow\n");
174                   exit(1);
175                 }
176               *store++ = 0;
177               return store;
178             }
179           x = 0;
180           continue;
181         }
182       x = (x << 7) ^ c ^ 128;
183     }
184 }
185
186 static void
187 read_str (FILE *fp, char **inbuf, unsigned *len)
188 {
189   unsigned char *buf = (unsigned char*)*inbuf;
190   if (!buf)
191     {
192       buf = xmalloc (1024);
193       *len = 1024;
194     }
195   int c;
196   unsigned ofs = 0;
197   while((c = getc (fp)) != 0)
198     {
199       if (c == EOF)
200         {
201           pool_debug (mypool, SAT_FATAL, "unexpected EOF\n");
202           exit (1);
203         }
204       /* Plus 1 as we also want to add the 0.  */
205       if (ofs + 1 >= *len)
206         {
207           *len += 256;
208           /* Don't realloc on the inbuf, it might be on the stack.  */
209           if (buf == (unsigned char*)*inbuf)
210             {
211               buf = xmalloc (*len);
212               memcpy (buf, *inbuf, *len - 256);
213             }
214           else
215             buf = xrealloc (buf, *len);
216         }
217       buf[ofs++] = c;
218     }
219   buf[ofs++] = 0;
220   *inbuf = (char*)buf;
221 }
222
223 static void
224 skip_item (FILE *fp, unsigned type, Id *idmap, unsigned numid, unsigned numrel)
225 {
226   switch (type)
227     {
228       case TYPE_ID:
229         read_id(fp, numid + numrel);   /* just check Id */
230         break;
231       case TYPE_U32:
232         read_u32(fp);
233         break;
234       case TYPE_ATTR_STRING:
235       case TYPE_STR:
236         while(read_u8(fp) != 0)
237           ;
238         break;
239       case TYPE_IDARRAY:
240       case TYPE_REL_IDARRAY:
241         while ((read_u8(fp) & 0xc0) != 0)
242           ;
243         break;
244       case TYPE_COUNT_NAMED:
245         {
246           unsigned count = read_id (fp, 0);
247           while (count--)
248             {
249               read_id (fp, numid);    /* Name */
250               unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
251               skip_item (fp, t, idmap, numid, numrel);
252             }
253         }
254         break;
255       case TYPE_COUNTED:
256         {
257           unsigned count = read_id (fp, 0);
258           unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
259           while (count--)
260             skip_item (fp, t, idmap, numid, numrel);
261         }
262         break;
263       case TYPE_ATTR_CHUNK:
264         read_id(fp, 0);
265         /* Fallthrough.  */
266       case TYPE_ATTR_INT:
267         read_id(fp, 0);
268         break;
269       case TYPE_ATTR_INTLIST:
270       case TYPE_ATTR_LOCALIDS:
271         while (read_id(fp, 0) != 0)
272           ;
273         break;
274       default:
275         pool_debug(mypool, SAT_FATAL, "unknown type %d\n", type);
276         exit(1);
277     }
278 }
279
280 static int
281 key_cmp (const void *pa, const void *pb)
282 {
283   struct key { Id name; unsigned type; };
284   struct key *a = (struct key*)pa;
285   struct key *b = (struct key*)pb;
286   return a->name - b->name;
287 }
288
289 static void
290 parse_repodata (FILE *fp, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
291 {
292   unsigned count = read_id (fp, 0);
293
294   while (count--)
295     {
296       Repodata *data;
297       read_id (fp, numid);  /* no name */
298       unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
299       if (type != TYPE_COUNT_NAMED)
300         {
301           skip_item (fp, type, idmap, numid, numrel);
302           continue;
303         }
304       unsigned c = read_id (fp, 0);
305       if (c == 0)
306         continue;
307       if (c != 2)
308         {
309           pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
310           exit (1);
311         }
312       read_id (fp, numid);  /* no name */
313       if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_STR)
314         {
315           pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
316           exit (1);
317         }
318       char buf[1024];
319       unsigned len = sizeof (buf);
320       char *filename = buf;
321       read_str (fp, &filename, &len);
322
323       read_id (fp, numid);  /* no name */
324       if (read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_COUNTED)
325         {
326           pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
327           exit (1);
328         }
329
330       unsigned nkeys = read_id (fp, 0);
331       if ((nkeys & 1) != 0
332           || read_id (fp, TYPE_ATTR_TYPE_MAX + 1) != TYPE_ID)
333         {
334           pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
335           exit (1);
336         }
337       nkeys >>= 1;
338
339       repo->nrepodata++;
340       data = xrealloc (repo->repodata, repo->nrepodata * sizeof (*data));
341       repo->repodata = data;
342       data += repo->nrepodata - 1;
343       memset (data, 0, sizeof (*data));
344       data->nkeys = nkeys;
345       if (data->nkeys)
346         {
347           unsigned i;
348           data->keys = xmalloc (data->nkeys * sizeof (data->keys[0]));
349           for (i = 0; i < data->nkeys; i++)
350           {
351               data->keys[i].name = idmap[read_id (fp, numid)];
352               data->keys[i].type = read_id (fp, 0);
353           }
354           qsort (data->keys, data->nkeys, sizeof (data->keys[0]), key_cmp);
355         }
356       data->name = strdup (filename);
357
358       if (filename != buf)
359         xfree (filename);
360     }
361 }
362
363 /*-----------------------------------------------------------------*/
364
365 struct key {
366   Id name;
367   Id type;
368   Id size;
369 };
370
371 // ----------------------------------------------
372
373 /*
374  * read repo from .solv file
375  *  and add it to pool
376  */
377
378 void
379 repo_add_solv(Repo *repo, FILE *fp)
380 {
381   Pool *pool = repo->pool;
382   int i, l;
383   unsigned int numid, numrel, numsolv;
384   unsigned int numkeys, numschemata, numinfo;
385   Attrstore *embedded_store = 0;
386
387   Offset sizeid;
388   Offset *str;                         /* map Id -> Offset into string space */
389   char *strsp;                         /* repo string space */
390   char *sp;                            /* pointer into string space */
391   Id *idmap;                           /* map of repo Ids to pool Ids */
392   Id id;
393   unsigned int hashmask, h;
394   int hh;
395   Id *hashtbl;
396   Id name, evr, did;
397   int flags;
398   Reldep *ran;
399   unsigned int size_idarray;
400   Id *idarraydatap, *idarraydataend;
401   Offset ido;
402   Solvable *s;
403   unsigned int solvflags;
404   unsigned int solvversion;
405   struct key *keys;
406   Id *schemadata, *schemadatap, *schemadataend;
407   Id *schemata, key;
408
409   mypool = pool;
410
411   if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
412     {
413       pool_debug(pool, SAT_FATAL, "not a SOLV file\n");
414       exit(1);
415     }
416   solvversion = read_u32(fp);
417   switch (solvversion)
418     {
419       case SOLV_VERSION_1:
420       case SOLV_VERSION_2:
421       case SOLV_VERSION_3:
422         break;
423       default:
424         pool_debug(pool, SAT_FATAL, "unsupported SOLV version\n");
425         exit(1);
426     }
427
428   pool_freeidhashes(pool);
429
430   numid = read_u32(fp);
431   numrel = read_u32(fp);
432   numsolv = read_u32(fp);
433   numkeys = read_u32(fp);
434   numschemata = read_u32(fp);
435   numinfo = read_u32(fp);
436   solvflags = read_u32(fp);
437
438   if (solvversion < SOLV_VERSION_3
439       && numinfo)
440     {
441       pool_debug(pool, SAT_FATAL, "unsupported SOLV format (has info)\n");
442       exit(1);
443     }
444
445   /*******  Part 1: string IDs  *****************************************/
446
447   sizeid = read_u32(fp);               /* size of string+Id space */
448
449   /*
450    * read strings and Ids
451    * 
452    */
453
454   
455   /*
456    * alloc buffers
457    */
458
459   /* alloc string buffer */
460   strsp = (char *)xrealloc(pool->ss.stringspace, pool->ss.sstrings + sizeid + 1);
461   /* alloc string offsets (Id -> Offset into string space) */
462   str = (Offset *)xrealloc(pool->ss.strings, (pool->ss.nstrings + numid) * sizeof(Offset));
463
464   pool->ss.stringspace = strsp;
465   pool->ss.strings = str;                      /* array of offsets into strsp, indexed by Id */
466
467   /* point to _BEHIND_ already allocated string/Id space */
468   strsp += pool->ss.sstrings;
469
470   /* alloc id map for name and rel Ids. this maps ids in the solv files
471    * to the ids in our pool */
472   idmap = (Id *)xcalloc(numid + numrel, sizeof(Id));
473
474   /*
475    * read new repo at end of pool
476    */
477   
478   if ((solvflags & SOLV_FLAG_PREFIX_POOL) == 0)
479     {
480       if (fread(strsp, sizeid, 1, fp) != 1)
481         {
482           pool_debug(pool, SAT_FATAL, "read error while reading strings\n");
483           exit(1);
484         }
485     }
486   else
487     {
488       unsigned int pfsize = read_u32 (fp);
489       char *prefix = xmalloc (pfsize);
490       char *pp = prefix;
491       char *old_str = "";
492       char *dest = strsp;
493       if (fread (prefix, pfsize, 1, fp) != 1)
494         {
495           pool_debug(pool, SAT_FATAL, "read error while reading strings\n");
496           exit(1);
497         }
498       for (i = 1; i < numid; i++)
499         {
500           int same = (unsigned char)*pp++;
501           size_t len = strlen (pp) + 1;
502           if (same)
503             memcpy (dest, old_str, same);
504           memcpy (dest + same, pp, len);
505           pp += len;
506           old_str = dest;
507           dest += same + len;
508         }
509       xfree (prefix);
510     }
511   strsp[sizeid] = 0;                   /* make string space \0 terminated */
512   sp = strsp;
513
514   /*
515    * build hashes for all read strings
516    * 
517    */
518   
519   hashmask = mkmask(pool->ss.nstrings + numid);
520
521 #if 0
522   POOL_DEBUG(SAT_DEBUG_STATS, "read %d strings\n", numid);
523   POOL_DEBUG(SAT_DEBUG_STATS, "string hash buckets: %d\n", hashmask + 1);
524 #endif
525
526   /*
527    * ensure sufficient hash size
528    */
529   
530   hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
531
532   /*
533    * fill hashtable with strings already in pool
534    */
535   
536   for (i = 1; i < pool->ss.nstrings; i++)  /* leave out our dummy zero id */
537     {
538       h = strhash(pool->ss.stringspace + pool->ss.strings[i]) & hashmask;
539       hh = HASHCHAIN_START;
540       while (hashtbl[h])
541         h = HASHCHAIN_NEXT(h, hh, hashmask);
542       hashtbl[h] = i;
543     }
544
545   /*
546    * run over string space, calculate offsets
547    * 
548    * build id map (maps solv Id -> pool Id)
549    */
550   
551   for (i = 1; i < numid; i++)
552     {
553       if (sp >= strsp + sizeid)
554         {
555           pool_debug(pool, SAT_FATAL, "not enough strings\n");
556           exit(1);
557         }
558       if (!*sp)                        /* empty string */
559         {
560           idmap[i] = ID_EMPTY;
561           sp++;
562           continue;
563         }
564
565       /* find hash slot */
566       h = strhash(sp) & hashmask;
567       hh = HASHCHAIN_START;
568       for (;;)
569         {
570           id = hashtbl[h];
571           if (id == 0)
572             break;
573           if (!strcmp(pool->ss.stringspace + pool->ss.strings[id], sp))
574             break;                     /* existing string */
575           h = HASHCHAIN_NEXT(h, hh, hashmask);
576         }
577
578       /* length == offset to next string */
579       l = strlen(sp) + 1;
580       if (id == ID_NULL)               /* end of hash chain -> new string */
581         {
582           id = pool->ss.nstrings++;
583           hashtbl[h] = id;
584           str[id] = pool->ss.sstrings;    /* save Offset */
585           if (sp != pool->ss.stringspace + pool->ss.sstrings)   /* not at end-of-buffer */
586             memmove(pool->ss.stringspace + pool->ss.sstrings, sp, l);   /* append to pool buffer */
587           pool->ss.sstrings += l;
588         }
589       idmap[i] = id;                   /* repo relative -> pool relative */
590       sp += l;                         /* next string */
591     }
592   xfree(hashtbl);
593   pool_shrink_strings(pool);           /* vacuum */
594
595   
596   /*******  Part 2: Relation IDs  ***************************************/
597
598   /*
599    * read RelDeps
600    * 
601    */
602   
603   if (numrel)
604     {
605       /* extend rels */
606       ran = (Reldep *)xrealloc(pool->rels, (pool->nrels + numrel) * sizeof(Reldep));
607       if (!ran)
608         {
609           pool_debug(pool, SAT_FATAL, "no mem for rel space\n");
610           exit(1);
611         }
612       pool->rels = ran;        /* extended rel space */
613
614       hashmask = mkmask(pool->nrels + numrel);
615 #if 0
616       POOL_DEBUG(SAT_DEBUG_STATS, "read %d rels\n", numrel);
617       POOL_DEBUG(SAT_DEBUG_STATS, "rel hash buckets: %d\n", hashmask + 1);
618 #endif
619       /*
620        * prep hash table with already existing RelDeps
621        */
622       
623       hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
624       for (i = 1; i < pool->nrels; i++)
625         {
626           h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
627           hh = HASHCHAIN_START;
628           while (hashtbl[h])
629             h = HASHCHAIN_NEXT(h, hh, hashmask);
630           hashtbl[h] = i;
631         }
632
633       /*
634        * read RelDeps from repo
635        */
636       
637       for (i = 0; i < numrel; i++)
638         {
639           name = read_id(fp, i + numid);        /* read (repo relative) Ids */
640           evr = read_id(fp, i + numid);
641           flags = read_u8(fp);
642           name = idmap[name];           /* map to (pool relative) Ids */
643           evr = idmap[evr];
644           h = relhash(name, evr, flags) & hashmask;
645           hh = HASHCHAIN_START;
646           for (;;)
647             {
648               id = hashtbl[h];
649               if (id == ID_NULL)        /* end of hash chain */
650                 break;
651               if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
652                 break;
653               h = HASHCHAIN_NEXT(h, hh, hashmask);
654             }
655           if (id == ID_NULL)            /* new RelDep */
656             {
657               id = pool->nrels++;
658               hashtbl[h] = id;
659               ran[id].name = name;
660               ran[id].evr = evr;
661               ran[id].flags = flags;
662             }
663           idmap[i + numid] = MAKERELDEP(id);   /* fill Id map */
664         }
665       xfree(hashtbl);
666       pool_shrink_rels(pool);           /* vacuum */
667     }
668
669
670   /*******  Part 3: Keys  ***********************************************/
671
672   keys = xcalloc(numkeys, sizeof(*keys));
673   /* keys start at 1 */
674   for (i = 1; i < numkeys; i++)
675     {
676       keys[i].name = idmap[read_id(fp, numid)];
677       keys[i].type = read_id(fp, 0);
678       keys[i].size = read_id(fp, 0);
679     }
680
681   /*******  Part 4: Schemata ********************************************/
682   
683   id = read_id(fp, 0);
684   schemadata = xcalloc(id, sizeof(Id));
685   schemadatap = schemadata;
686   schemadataend = schemadata + id;
687   schemata = xcalloc(numschemata, sizeof(Id));
688   for (i = 0; i < numschemata; i++)
689     {
690       schemata[i] = schemadatap - schemadata;
691       schemadatap = read_idarray(fp, numid, 0, schemadatap, schemadataend, 0);
692     }
693
694   /*******  Part 5: Info  ***********************************************/
695   /* we skip the info for now... */
696   for (i = 0; i < numinfo; i++)
697     {
698       unsigned name = idmap[read_id (fp, numid)];
699       unsigned type = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
700       if (type == TYPE_COUNT_NAMED
701           && !strcmp (id2str (pool, name), "repodata"))
702         parse_repodata (fp, idmap, numid, numrel, repo);
703       else
704         skip_item (fp, type, idmap, numid, numrel);
705     }
706
707   /*******  Part 6: packed sizes (optional)  ****************************/
708   char *exists = 0;
709   if ((solvflags & SOLV_FLAG_PACKEDSIZES) != 0)
710     {
711       exists = xmalloc (numsolv);
712       for (i = 0; i < numsolv; i++)
713         exists[i] = read_id(fp, 0) != 0;
714     }
715
716   /*******  Part 7: item data *******************************************/
717
718   /* calculate idarray size */
719   size_idarray = 0;
720   for (i = 1; i < numkeys; i++)
721     {
722       id = keys[i].name;
723       if ((keys[i].type == TYPE_IDARRAY || keys[i].type == TYPE_REL_IDARRAY)
724           && id >= INTERESTED_START && id <= INTERESTED_END)
725         size_idarray += keys[i].size;
726     }
727
728   /* allocate needed space in repo */
729   if (size_idarray)
730     {
731       repo_reserve_ids(repo, 0, size_idarray);
732       idarraydatap = repo->idarraydata + repo->idarraysize;
733       repo->idarraysize += size_idarray;
734       idarraydataend = repo->idarraydata + repo->idarraysize;
735       repo->lastoff = 0;
736     }
737   else
738     {
739       idarraydatap = 0;
740       idarraydataend = 0;
741     }
742
743   /* read solvables */
744   s = pool_id2solvable(pool, repo_add_solvable_block(repo, numsolv));
745
746   if ((solvflags & SOLV_FLAG_VERTICAL) != 0)
747     {
748       Id *solvschema = xcalloc(numsolv, sizeof(Id));
749       unsigned char *used = xmalloc(numschemata);
750       Solvable *sstart = s;
751       Id type;
752
753       for (i = 0; i < numsolv; i++)
754         solvschema[i] = read_id(fp, numschemata);
755       for (key = 1; key < numkeys; key++)
756         {
757           id = keys[key].name;
758           type = keys[key].type;
759           memset(used, 0, numschemata);
760           for (i = 0; i < numschemata; i++)
761             {
762               Id *keyp = schemadata + schemata[i];
763               while (*keyp)
764                 if (*keyp++ == key)
765                   {
766                     used[i] = 1;
767                     break;
768                   }
769             }
770           for (i = 0, s = sstart; i < numsolv; i++, s++)
771              {
772               if (!used[solvschema[i]])
773                 continue;
774               switch (type)
775                 {
776                 case TYPE_ID:
777                   did = idmap[read_id(fp, numid + numrel)];
778                   if (id == SOLVABLE_NAME)
779                     s->name = did;
780                   else if (id == SOLVABLE_ARCH)
781                     s->arch = did;
782                   else if (id == SOLVABLE_EVR)
783                     s->evr = did;
784                   else if (id == SOLVABLE_VENDOR)
785                     s->vendor = did;
786                   break;
787                 case TYPE_U32:
788                   h = read_u32(fp);
789                   if (id == RPM_RPMDBID)
790                     {
791                       if (!repo->rpmdbid)
792                         repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
793                       repo->rpmdbid[i] = h;
794                     }
795                   break;
796                 case TYPE_STR:
797                   while(read_u8(fp) != 0)
798                     ;
799                   break;
800                 case TYPE_IDARRAY:
801                 case TYPE_REL_IDARRAY:
802                   if (id < INTERESTED_START || id > INTERESTED_END)
803                     {
804                       /* not interested in array */
805                       while ((read_u8(fp) & 0xc0) != 0)
806                         ;
807                       break;
808                     }
809                   ido = idarraydatap - repo->idarraydata;
810                   idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, type == TYPE_REL_IDARRAY);
811                   if (id == SOLVABLE_PROVIDES)
812                     s->provides = ido;
813                   else if (id == SOLVABLE_OBSOLETES)
814                     s->obsoletes = ido;
815                   else if (id == SOLVABLE_CONFLICTS)
816                     s->conflicts = ido;
817                   else if (id == SOLVABLE_REQUIRES)
818                     s->requires = ido;
819                   else if (id == SOLVABLE_RECOMMENDS)
820                     s->recommends= ido;
821                   else if (id == SOLVABLE_SUPPLEMENTS)
822                     s->supplements = ido;
823                   else if (id == SOLVABLE_SUGGESTS)
824                     s->suggests = ido;
825                   else if (id == SOLVABLE_ENHANCES)
826                     s->enhances = ido;
827                   else if (id == SOLVABLE_FRESHENS)
828                     s->freshens = ido;
829                   break;
830                 case TYPE_ATTR_INT:
831                 case TYPE_ATTR_CHUNK:
832                 case TYPE_ATTR_STRING:
833                 case TYPE_ATTR_INTLIST:
834                 case TYPE_ATTR_LOCALIDS:
835                   if (!embedded_store)
836                     embedded_store = new_store (pool);
837                   add_attr_from_file (embedded_store, i, id, type, idmap, numid, fp);
838                   break;
839                 }
840             }
841         }
842       xfree(used);
843       xfree(solvschema);
844       xfree(idmap);
845       xfree(schemata);
846       xfree(schemadata);
847       xfree(keys);
848       mypool = 0;
849       return;
850     }
851   for (i = 0; i < numsolv; i++, s++)
852     {
853       if (exists && !exists[i])
854         continue;
855       Id *keyp = schemadata + schemata[read_id(fp, numschemata)];
856       while ((key = *keyp++) != 0)
857         {
858           id = keys[key].name;
859           switch (keys[key].type)
860             {
861             case TYPE_ID:
862               did = idmap[read_id(fp, numid + numrel)];
863               if (id == SOLVABLE_NAME)
864                 s->name = did;
865               else if (id == SOLVABLE_ARCH)
866                 s->arch = did;
867               else if (id == SOLVABLE_EVR)
868                 s->evr = did;
869               else if (id == SOLVABLE_VENDOR)
870                 s->vendor = did;
871 #if 0
872               POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did));
873 #endif
874               break;
875             case TYPE_U32:
876               h = read_u32(fp);
877 #if 0
878               POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %u\n", id2str(pool, id), h);
879 #endif
880               if (id == RPM_RPMDBID)
881                 {
882                   if (!repo->rpmdbid)
883                     repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
884                   repo->rpmdbid[i] = h;
885                 }
886               break;
887             case TYPE_STR:
888               while(read_u8(fp) != 0)
889                 ;
890               break;
891             case TYPE_IDARRAY:
892             case TYPE_REL_IDARRAY:
893               if (id < INTERESTED_START || id > INTERESTED_END)
894                 {
895                   /* not interested in array */
896                   while ((read_u8(fp) & 0xc0) != 0)
897                     ;
898                   break;
899                 }
900               ido = idarraydatap - repo->idarraydata;
901               idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, keys[key].type == TYPE_REL_IDARRAY);
902               if (id == SOLVABLE_PROVIDES)
903                 s->provides = ido;
904               else if (id == SOLVABLE_OBSOLETES)
905                 s->obsoletes = ido;
906               else if (id == SOLVABLE_CONFLICTS)
907                 s->conflicts = ido;
908               else if (id == SOLVABLE_REQUIRES)
909                 s->requires = ido;
910               else if (id == SOLVABLE_RECOMMENDS)
911                 s->recommends= ido;
912               else if (id == SOLVABLE_SUPPLEMENTS)
913                 s->supplements = ido;
914               else if (id == SOLVABLE_SUGGESTS)
915                 s->suggests = ido;
916               else if (id == SOLVABLE_ENHANCES)
917                 s->enhances = ido;
918               else if (id == SOLVABLE_FRESHENS)
919                 s->freshens = ido;
920 #if 0
921               POOL_DEBUG(SAT_DEBUG_STATS, "%s ->\n", id2str(pool, id));
922               for (; repo->idarraydata[ido]; ido++)
923                 POOL_DEBUG(SAT_DEBUG_STATS,"  %s\n", dep2str(pool, repo->idarraydata[ido]));
924 #endif
925               break;
926             case TYPE_ATTR_INT:
927             case TYPE_ATTR_CHUNK:
928             case TYPE_ATTR_STRING:
929             case TYPE_ATTR_INTLIST:
930             case TYPE_ATTR_LOCALIDS:
931               if (!embedded_store)
932                 embedded_store = new_store (pool);
933               add_attr_from_file (embedded_store, i, id, keys[key].type, idmap, numid, fp);
934               break;
935             }
936         }
937     }
938   xfree(exists);
939   if (embedded_store)
940     {
941       attr_store_pack (embedded_store);
942       /* If we have any attributes we also have pages.  */
943       read_or_setup_pages (fp, embedded_store);
944       /* The NULL name here means embedded attributes.  */
945       repo_add_attrstore (repo, embedded_store, NULL);
946     }
947   xfree(idmap);
948   xfree(schemata);
949   xfree(schemadata);
950   xfree(keys);
951   mypool = 0;
952 }
953
954 // EOF