Handle most of the susetags tags. Major exception is 'Shr', where I'm
[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 (max && 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, unsigned numid, unsigned numrel)
225 {
226   switch (type)
227     {
228       case TYPE_VOID:
229         break;
230       case TYPE_ID:
231         read_id(fp, numid + numrel);   /* just check Id */
232         break;
233       case TYPE_U32:
234         read_u32(fp);
235         break;
236       case TYPE_ATTR_STRING:
237       case TYPE_STR:
238         while(read_u8(fp) != 0)
239           ;
240         break;
241       case TYPE_IDARRAY:
242       case TYPE_IDVALUEARRAY:
243       case TYPE_IDVALUEVALUEARRAY:
244       case TYPE_REL_IDARRAY:
245         while ((read_u8(fp) & 0xc0) != 0)
246           ;
247         break;
248       case TYPE_COUNT_NAMED:
249         {
250           unsigned count = read_id (fp, 0);
251           while (count--)
252             {
253               read_id (fp, numid);    /* Name */
254               unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
255               skip_item (fp, t, numid, numrel);
256             }
257         }
258         break;
259       case TYPE_COUNTED:
260         {
261           unsigned count = read_id (fp, 0);
262           unsigned t = read_id (fp, TYPE_ATTR_TYPE_MAX + 1);
263           while (count--)
264             skip_item (fp, t, numid, numrel);
265         }
266         break;
267       case TYPE_ATTR_CHUNK:
268         read_id(fp, 0);
269         /* Fallthrough.  */
270       case TYPE_ATTR_INT:
271         read_id(fp, 0);
272         break;
273       case TYPE_ATTR_INTLIST:
274       case TYPE_ATTR_LOCALIDS:
275         while (read_id(fp, 0) != 0)
276           ;
277         break;
278       default:
279         pool_debug(mypool, SAT_FATAL, "unknown type %d\n", type);
280         exit(1);
281     }
282 }
283
284 static int
285 key_cmp (const void *pa, const void *pb)
286 {
287   struct key { Id name; unsigned type; };
288   struct key *a = (struct key*)pa;
289   struct key *b = (struct key*)pb;
290   return a->name - b->name;
291 }
292
293 struct key {
294   Id name;
295   Id type;
296   Id size;
297 };
298
299 static void
300 parse_repodata (FILE *fp, Id *keyp, struct key *keys, Id *idmap, unsigned numid, unsigned numrel, Repo *repo)
301 {
302   Id key, id;
303   Id *ida, *ide;
304   Repodata *data;
305   int i, n;
306
307   repo->repodata = xrealloc(repo->repodata, (repo->nrepodata + 1) * sizeof (*data));
308   data = repo->repodata + repo->nrepodata++;
309   memset(data, 0, sizeof(*data));
310
311   while ((key = *keyp++) != 0)
312     {
313       id = keys[key].name;
314       switch (keys[key].type)
315         {
316         case TYPE_IDVALUEARRAY:
317           if (id != REPODATA_KEYS)
318             {
319               skip_item(fp, TYPE_IDVALUEARRAY, numid, numrel);
320               break;
321             }
322           ida = xcalloc(keys[key].size, sizeof(Id));
323           ide = read_idarray(fp, 0, 0, ida, ida + keys[key].size, 0);
324           n = ide - ida - 1;
325           if (n & 1)
326             {
327               pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
328               exit (1);
329             }
330           data->nkeys = n >> 1;
331           data->keys = xmalloc2(data->nkeys, sizeof(data->keys[0]));
332           for (i = 0, ide = ida; i < data->nkeys; i++)
333             {
334               if (*ide >= numid)
335                 {
336                   pool_debug (mypool, SAT_FATAL, "invalid attribute data\n");
337                   exit (1);
338                 }
339               data->keys[i].name = idmap[*ide++];
340               data->keys[i].type = *ide++;
341             }
342           xfree(ida);
343           qsort(data->keys, data->nkeys, sizeof(data->keys[0]), key_cmp);
344           break;
345         case TYPE_STR:
346           if (id != REPODATA_LOCATION)
347             skip_item(fp, TYPE_STR, numid, numrel);
348           else
349             {
350               char buf[1024];
351               unsigned len = sizeof (buf);
352               char *filename = buf;
353               read_str(fp, &filename, &len);
354               data->location = strdup(filename);
355               if (filename != buf)
356                 free(filename);
357             }
358           break;
359         default:
360           skip_item(fp, keys[key].type, numid, numrel);
361           break;
362         }
363     }
364 }
365
366 /*-----------------------------------------------------------------*/
367
368
369 void
370 skip_schema(FILE *fp, Id *keyp, struct key *keys, unsigned int numid, unsigned int numrel)
371 {
372   Id key;
373   while ((key = *keyp++) != 0)
374     skip_item(fp, keys[key].type, numid, numrel);
375 }
376
377 // ----------------------------------------------
378
379 /*
380  * read repo from .solv file
381  *  and add it to pool
382  */
383
384 void
385 repo_add_solv(Repo *repo, FILE *fp)
386 {
387   Pool *pool = repo->pool;
388   int i, l;
389   unsigned int numid, numrel, numsolv;
390   unsigned int numkeys, numschemata, numinfo;
391   Attrstore *embedded_store = 0;
392
393   Offset sizeid;
394   Offset *str;                         /* map Id -> Offset into string space */
395   char *strsp;                         /* repo string space */
396   char *sp;                            /* pointer into string space */
397   Id *idmap;                           /* map of repo Ids to pool Ids */
398   Id id;
399   unsigned int hashmask, h;
400   int hh;
401   Id *hashtbl;
402   Id name, evr, did;
403   int flags;
404   Reldep *ran;
405   unsigned int size_idarray;
406   Id *idarraydatap, *idarraydataend;
407   Offset ido;
408   Solvable *s;
409   unsigned int solvflags;
410   unsigned int solvversion;
411   struct key *keys;
412   Id *schemadata, *schemadatap, *schemadataend;
413   Id *schemata, key;
414
415   mypool = pool;
416
417   if (read_u32(fp) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V'))
418     {
419       pool_debug(pool, SAT_FATAL, "not a SOLV file\n");
420       exit(1);
421     }
422   solvversion = read_u32(fp);
423   switch (solvversion)
424     {
425       case SOLV_VERSION_1:
426       case SOLV_VERSION_2:
427       case SOLV_VERSION_3:
428         break;
429       default:
430         pool_debug(pool, SAT_FATAL, "unsupported SOLV version\n");
431         exit(1);
432     }
433
434   pool_freeidhashes(pool);
435
436   numid = read_u32(fp);
437   numrel = read_u32(fp);
438   numsolv = read_u32(fp);
439   numkeys = read_u32(fp);
440   numschemata = read_u32(fp);
441   numinfo = read_u32(fp);
442   solvflags = read_u32(fp);
443
444   if (solvversion < SOLV_VERSION_3
445       && numinfo)
446     {
447       pool_debug(pool, SAT_FATAL, "unsupported SOLV format (has info)\n");
448       exit(1);
449     }
450
451   /*******  Part 1: string IDs  *****************************************/
452
453   sizeid = read_u32(fp);               /* size of string+Id space */
454
455   /*
456    * read strings and Ids
457    * 
458    */
459
460   
461   /*
462    * alloc buffers
463    */
464
465   /* alloc string buffer */
466   strsp = (char *)xrealloc(pool->ss.stringspace, pool->ss.sstrings + sizeid + 1);
467   /* alloc string offsets (Id -> Offset into string space) */
468   str = (Offset *)xrealloc(pool->ss.strings, (pool->ss.nstrings + numid) * sizeof(Offset));
469
470   pool->ss.stringspace = strsp;
471   pool->ss.strings = str;                      /* array of offsets into strsp, indexed by Id */
472
473   /* point to _BEHIND_ already allocated string/Id space */
474   strsp += pool->ss.sstrings;
475
476   /* alloc id map for name and rel Ids. this maps ids in the solv files
477    * to the ids in our pool */
478   idmap = (Id *)xcalloc(numid + numrel, sizeof(Id));
479
480   /*
481    * read new repo at end of pool
482    */
483   
484   if ((solvflags & SOLV_FLAG_PREFIX_POOL) == 0)
485     {
486       if (fread(strsp, sizeid, 1, fp) != 1)
487         {
488           pool_debug(pool, SAT_FATAL, "read error while reading strings\n");
489           exit(1);
490         }
491     }
492   else
493     {
494       unsigned int pfsize = read_u32 (fp);
495       char *prefix = xmalloc (pfsize);
496       char *pp = prefix;
497       char *old_str = "";
498       char *dest = strsp;
499       if (fread (prefix, pfsize, 1, fp) != 1)
500         {
501           pool_debug(pool, SAT_FATAL, "read error while reading strings\n");
502           exit(1);
503         }
504       for (i = 1; i < numid; i++)
505         {
506           int same = (unsigned char)*pp++;
507           size_t len = strlen (pp) + 1;
508           if (same)
509             memcpy (dest, old_str, same);
510           memcpy (dest + same, pp, len);
511           pp += len;
512           old_str = dest;
513           dest += same + len;
514         }
515       xfree (prefix);
516     }
517   strsp[sizeid] = 0;                   /* make string space \0 terminated */
518   sp = strsp;
519
520   /*
521    * build hashes for all read strings
522    * 
523    */
524   
525   hashmask = mkmask(pool->ss.nstrings + numid);
526
527 #if 0
528   POOL_DEBUG(SAT_DEBUG_STATS, "read %d strings\n", numid);
529   POOL_DEBUG(SAT_DEBUG_STATS, "string hash buckets: %d\n", hashmask + 1);
530 #endif
531
532   /*
533    * ensure sufficient hash size
534    */
535   
536   hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
537
538   /*
539    * fill hashtable with strings already in pool
540    */
541   
542   for (i = 1; i < pool->ss.nstrings; i++)  /* leave out our dummy zero id */
543     {
544       h = strhash(pool->ss.stringspace + pool->ss.strings[i]) & hashmask;
545       hh = HASHCHAIN_START;
546       while (hashtbl[h])
547         h = HASHCHAIN_NEXT(h, hh, hashmask);
548       hashtbl[h] = i;
549     }
550
551   /*
552    * run over string space, calculate offsets
553    * 
554    * build id map (maps solv Id -> pool Id)
555    */
556   
557   for (i = 1; i < numid; i++)
558     {
559       if (sp >= strsp + sizeid)
560         {
561           pool_debug(pool, SAT_FATAL, "not enough strings\n");
562           exit(1);
563         }
564       if (!*sp)                        /* empty string */
565         {
566           idmap[i] = ID_EMPTY;
567           sp++;
568           continue;
569         }
570
571       /* find hash slot */
572       h = strhash(sp) & hashmask;
573       hh = HASHCHAIN_START;
574       for (;;)
575         {
576           id = hashtbl[h];
577           if (id == 0)
578             break;
579           if (!strcmp(pool->ss.stringspace + pool->ss.strings[id], sp))
580             break;                     /* existing string */
581           h = HASHCHAIN_NEXT(h, hh, hashmask);
582         }
583
584       /* length == offset to next string */
585       l = strlen(sp) + 1;
586       if (id == ID_NULL)               /* end of hash chain -> new string */
587         {
588           id = pool->ss.nstrings++;
589           hashtbl[h] = id;
590           str[id] = pool->ss.sstrings;    /* save Offset */
591           if (sp != pool->ss.stringspace + pool->ss.sstrings)   /* not at end-of-buffer */
592             memmove(pool->ss.stringspace + pool->ss.sstrings, sp, l);   /* append to pool buffer */
593           pool->ss.sstrings += l;
594         }
595       idmap[i] = id;                   /* repo relative -> pool relative */
596       sp += l;                         /* next string */
597     }
598   xfree(hashtbl);
599   pool_shrink_strings(pool);           /* vacuum */
600
601   
602   /*******  Part 2: Relation IDs  ***************************************/
603
604   /*
605    * read RelDeps
606    * 
607    */
608   
609   if (numrel)
610     {
611       /* extend rels */
612       ran = (Reldep *)xrealloc(pool->rels, (pool->nrels + numrel) * sizeof(Reldep));
613       if (!ran)
614         {
615           pool_debug(pool, SAT_FATAL, "no mem for rel space\n");
616           exit(1);
617         }
618       pool->rels = ran;        /* extended rel space */
619
620       hashmask = mkmask(pool->nrels + numrel);
621 #if 0
622       POOL_DEBUG(SAT_DEBUG_STATS, "read %d rels\n", numrel);
623       POOL_DEBUG(SAT_DEBUG_STATS, "rel hash buckets: %d\n", hashmask + 1);
624 #endif
625       /*
626        * prep hash table with already existing RelDeps
627        */
628       
629       hashtbl = (Id *)xcalloc(hashmask + 1, sizeof(Id));
630       for (i = 1; i < pool->nrels; i++)
631         {
632           h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
633           hh = HASHCHAIN_START;
634           while (hashtbl[h])
635             h = HASHCHAIN_NEXT(h, hh, hashmask);
636           hashtbl[h] = i;
637         }
638
639       /*
640        * read RelDeps from repo
641        */
642       
643       for (i = 0; i < numrel; i++)
644         {
645           name = read_id(fp, i + numid);        /* read (repo relative) Ids */
646           evr = read_id(fp, i + numid);
647           flags = read_u8(fp);
648           name = idmap[name];           /* map to (pool relative) Ids */
649           evr = idmap[evr];
650           h = relhash(name, evr, flags) & hashmask;
651           hh = HASHCHAIN_START;
652           for (;;)
653             {
654               id = hashtbl[h];
655               if (id == ID_NULL)        /* end of hash chain */
656                 break;
657               if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
658                 break;
659               h = HASHCHAIN_NEXT(h, hh, hashmask);
660             }
661           if (id == ID_NULL)            /* new RelDep */
662             {
663               id = pool->nrels++;
664               hashtbl[h] = id;
665               ran[id].name = name;
666               ran[id].evr = evr;
667               ran[id].flags = flags;
668             }
669           idmap[i + numid] = MAKERELDEP(id);   /* fill Id map */
670         }
671       xfree(hashtbl);
672       pool_shrink_rels(pool);           /* vacuum */
673     }
674
675
676   /*******  Part 3: Keys  ***********************************************/
677
678   keys = xcalloc(numkeys, sizeof(*keys));
679   /* keys start at 1 */
680   for (i = 1; i < numkeys; i++)
681     {
682       keys[i].name = idmap[read_id(fp, numid)];
683       keys[i].type = read_id(fp, 0);
684       keys[i].size = read_id(fp, 0);
685     }
686
687   /*******  Part 4: Schemata ********************************************/
688   
689   id = read_id(fp, 0);
690   schemadata = xcalloc(id, sizeof(Id));
691   schemadatap = schemadata;
692   schemadataend = schemadata + id;
693   schemata = xcalloc(numschemata, sizeof(Id));
694   for (i = 0; i < numschemata; i++)
695     {
696       schemata[i] = schemadatap - schemadata;
697       schemadatap = read_idarray(fp, numid, 0, schemadatap, schemadataend, 0);
698     }
699
700   /*******  Part 5: Info  ***********************************************/
701   for (i = 0; i < numinfo; i++)
702     {
703       /* for now we're just interested in data that starts with
704        * the repodata_external id
705        */
706       Id *keyp = schemadata + schemata[read_id(fp, numschemata)];
707       key = *keyp;
708       if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == TYPE_VOID)
709         {
710           /* external data for some ids */
711           parse_repodata(fp, keyp, keys, idmap, numid, numrel, repo);
712         }
713       else
714         skip_schema(fp, keyp, keys, numid, numrel);
715     }
716
717   /*******  Part 6: packed sizes (optional)  ****************************/
718   char *exists = 0;
719   if ((solvflags & SOLV_FLAG_PACKEDSIZES) != 0)
720     {
721       exists = xmalloc (numsolv);
722       for (i = 0; i < numsolv; i++)
723         exists[i] = read_id(fp, 0) != 0;
724     }
725
726   /*******  Part 7: item data *******************************************/
727
728   /* calculate idarray size */
729   size_idarray = 0;
730   for (i = 1; i < numkeys; i++)
731     {
732       id = keys[i].name;
733       if ((keys[i].type == TYPE_IDARRAY || keys[i].type == TYPE_REL_IDARRAY)
734           && id >= INTERESTED_START && id <= INTERESTED_END)
735         size_idarray += keys[i].size;
736     }
737
738   /* allocate needed space in repo */
739   if (size_idarray)
740     {
741       repo_reserve_ids(repo, 0, size_idarray);
742       idarraydatap = repo->idarraydata + repo->idarraysize;
743       repo->idarraysize += size_idarray;
744       idarraydataend = repo->idarraydata + repo->idarraysize;
745       repo->lastoff = 0;
746     }
747   else
748     {
749       idarraydatap = 0;
750       idarraydataend = 0;
751     }
752
753   /* read solvables */
754   s = pool_id2solvable(pool, repo_add_solvable_block(repo, numsolv));
755
756   if ((solvflags & SOLV_FLAG_VERTICAL) != 0)
757     {
758       Id *solvschema = xcalloc(numsolv, sizeof(Id));
759       unsigned char *used = xmalloc(numschemata);
760       Solvable *sstart = s;
761       Id type;
762
763       for (i = 0; i < numsolv; i++)
764         solvschema[i] = read_id(fp, numschemata);
765       for (key = 1; key < numkeys; key++)
766         {
767           id = keys[key].name;
768           type = keys[key].type;
769           memset(used, 0, numschemata);
770           for (i = 0; i < numschemata; i++)
771             {
772               Id *keyp = schemadata + schemata[i];
773               while (*keyp)
774                 if (*keyp++ == key)
775                   {
776                     used[i] = 1;
777                     break;
778                   }
779             }
780           for (i = 0, s = sstart; i < numsolv; i++, s++)
781              {
782               if (!used[solvschema[i]])
783                 continue;
784               switch (type)
785                 {
786                 case TYPE_ID:
787                   did = idmap[read_id(fp, numid + numrel)];
788                   if (id == SOLVABLE_NAME)
789                     s->name = did;
790                   else if (id == SOLVABLE_ARCH)
791                     s->arch = did;
792                   else if (id == SOLVABLE_EVR)
793                     s->evr = did;
794                   else if (id == SOLVABLE_VENDOR)
795                     s->vendor = did;
796                   break;
797                 case TYPE_U32:
798                   h = read_u32(fp);
799                   if (id == RPM_RPMDBID)
800                     {
801                       if (!repo->rpmdbid)
802                         repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
803                       repo->rpmdbid[i] = h;
804                     }
805                   break;
806                 case TYPE_STR:
807                   while(read_u8(fp) != 0)
808                     ;
809                   break;
810                 case TYPE_IDARRAY:
811                 case TYPE_REL_IDARRAY:
812                   if (id < INTERESTED_START || id > INTERESTED_END)
813                     {
814                       /* not interested in array */
815                       while ((read_u8(fp) & 0xc0) != 0)
816                         ;
817                       break;
818                     }
819                   ido = idarraydatap - repo->idarraydata;
820                   idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, type == TYPE_REL_IDARRAY);
821                   if (id == SOLVABLE_PROVIDES)
822                     s->provides = ido;
823                   else if (id == SOLVABLE_OBSOLETES)
824                     s->obsoletes = ido;
825                   else if (id == SOLVABLE_CONFLICTS)
826                     s->conflicts = ido;
827                   else if (id == SOLVABLE_REQUIRES)
828                     s->requires = ido;
829                   else if (id == SOLVABLE_RECOMMENDS)
830                     s->recommends= ido;
831                   else if (id == SOLVABLE_SUPPLEMENTS)
832                     s->supplements = ido;
833                   else if (id == SOLVABLE_SUGGESTS)
834                     s->suggests = ido;
835                   else if (id == SOLVABLE_ENHANCES)
836                     s->enhances = ido;
837                   else if (id == SOLVABLE_FRESHENS)
838                     s->freshens = ido;
839                   break;
840                 case TYPE_VOID:
841                 case TYPE_ATTR_INT:
842                 case TYPE_ATTR_CHUNK:
843                 case TYPE_ATTR_STRING:
844                 case TYPE_ATTR_INTLIST:
845                 case TYPE_ATTR_LOCALIDS:
846                   if (!embedded_store)
847                     embedded_store = new_store (pool);
848                   add_attr_from_file (embedded_store, i, id, type, idmap, numid, fp);
849                   break;
850                 }
851             }
852         }
853       xfree(used);
854       xfree(solvschema);
855       xfree(idmap);
856       xfree(schemata);
857       xfree(schemadata);
858       xfree(keys);
859       mypool = 0;
860       return;
861     }
862   for (i = 0; i < numsolv; i++, s++)
863     {
864       if (exists && !exists[i])
865         continue;
866       Id *keyp = schemadata + schemata[read_id(fp, numschemata)];
867       while ((key = *keyp++) != 0)
868         {
869           id = keys[key].name;
870           switch (keys[key].type)
871             {
872             case TYPE_ID:
873               did = idmap[read_id(fp, numid + numrel)];
874               if (id == SOLVABLE_NAME)
875                 s->name = did;
876               else if (id == SOLVABLE_ARCH)
877                 s->arch = did;
878               else if (id == SOLVABLE_EVR)
879                 s->evr = did;
880               else if (id == SOLVABLE_VENDOR)
881                 s->vendor = did;
882 #if 0
883               POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did));
884 #endif
885               break;
886             case TYPE_U32:
887               h = read_u32(fp);
888 #if 0
889               POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %u\n", id2str(pool, id), h);
890 #endif
891               if (id == RPM_RPMDBID)
892                 {
893                   if (!repo->rpmdbid)
894                     repo->rpmdbid = (Id *)xcalloc(numsolv, sizeof(Id));
895                   repo->rpmdbid[i] = h;
896                 }
897               break;
898             case TYPE_STR:
899               while(read_u8(fp) != 0)
900                 ;
901               break;
902             case TYPE_IDARRAY:
903             case TYPE_REL_IDARRAY:
904               if (id < INTERESTED_START || id > INTERESTED_END)
905                 {
906                   /* not interested in array */
907                   while ((read_u8(fp) & 0xc0) != 0)
908                     ;
909                   break;
910                 }
911               ido = idarraydatap - repo->idarraydata;
912               idarraydatap = read_idarray(fp, numid + numrel, idmap, idarraydatap, idarraydataend, keys[key].type == TYPE_REL_IDARRAY);
913               if (id == SOLVABLE_PROVIDES)
914                 s->provides = ido;
915               else if (id == SOLVABLE_OBSOLETES)
916                 s->obsoletes = ido;
917               else if (id == SOLVABLE_CONFLICTS)
918                 s->conflicts = ido;
919               else if (id == SOLVABLE_REQUIRES)
920                 s->requires = ido;
921               else if (id == SOLVABLE_RECOMMENDS)
922                 s->recommends= ido;
923               else if (id == SOLVABLE_SUPPLEMENTS)
924                 s->supplements = ido;
925               else if (id == SOLVABLE_SUGGESTS)
926                 s->suggests = ido;
927               else if (id == SOLVABLE_ENHANCES)
928                 s->enhances = ido;
929               else if (id == SOLVABLE_FRESHENS)
930                 s->freshens = ido;
931 #if 0
932               POOL_DEBUG(SAT_DEBUG_STATS, "%s ->\n", id2str(pool, id));
933               for (; repo->idarraydata[ido]; ido++)
934                 POOL_DEBUG(SAT_DEBUG_STATS,"  %s\n", dep2str(pool, repo->idarraydata[ido]));
935 #endif
936               break;
937             case TYPE_VOID:
938             case TYPE_ATTR_INT:
939             case TYPE_ATTR_CHUNK:
940             case TYPE_ATTR_STRING:
941             case TYPE_ATTR_INTLIST:
942             case TYPE_ATTR_LOCALIDS:
943               if (!embedded_store)
944                 embedded_store = new_store (pool);
945               add_attr_from_file (embedded_store, i, id, keys[key].type, idmap, numid, fp);
946               break;
947             default:
948               skip_item(fp, keys[key].type, numid, numrel);
949             }
950         }
951     }
952   xfree(exists);
953   if (embedded_store)
954     {
955       attr_store_pack (embedded_store);
956       /* If we have any attributes we also have pages.  */
957       read_or_setup_pages (fp, embedded_store);
958       /* The NULL name here means embedded attributes.  */
959       repo_add_attrstore (repo, embedded_store, NULL);
960     }
961   xfree(idmap);
962   xfree(schemata);
963   xfree(schemadata);
964   xfree(keys);
965   mypool = 0;
966 }
967
968 // EOF