more flexibility in naming attribute files,
[platform/upstream/libsolv.git] / tools / dumpsolv.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 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12
13 static char *attrname = 0;
14
15 #include "pool.h"
16 #include "repo_solv.h"
17 #if 0
18 #include "attr_store.h"
19 #include "attr_store_p.h"
20
21 static void
22 dump_attrs_1 (Attrstore *s, unsigned int entry)
23 {
24   attr_iterator ai;
25   FOR_ATTRS (s, entry, &ai)
26     {
27       fprintf (stdout, "%s:", id2str (s->pool, ai.name));
28       switch (ai.type)
29         {
30         case TYPE_ATTR_INT:
31           fprintf (stdout, "int  %u\n", ai.as_int);
32           break;
33         case TYPE_ATTR_CHUNK:
34           {
35             const char *str = attr_retrieve_blob (s, ai.as_chunk[0], ai.as_chunk[1]);
36             if (str)
37               fprintf (stdout, "blob %s\n", str);
38             else
39               fprintf (stdout, "blob %u+%u\n", ai.as_chunk[0], ai.as_chunk[1]);
40           }
41           break;
42         case TYPE_ATTR_STRING:
43           fprintf (stdout, "str  %s\n", ai.as_string);
44           break;
45         case TYPE_ATTR_INTLIST:
46           {
47             fprintf (stdout, "lint\n ");
48             while (1)
49               {
50                 int val;
51                 get_num (ai.as_numlist, val);
52                 fprintf (stdout, " %d", (val & 63) | ((val >> 1) & ~63));
53                 if (!(val & 64))
54                   break;
55               }
56             fprintf (stdout, "\n");
57             break;
58           }
59         case TYPE_ATTR_LOCALIDS:
60           {
61             fprintf (stdout, "lids");
62             while (1)
63               {
64                 Id val;
65                 get_num (ai.as_numlist, val);
66                 if (!val)
67                   break;
68                 fprintf (stdout, "\n  %s(%d)", localid2str (s, val), val);
69               }
70             fprintf (stdout, "\n");
71             break;
72           }
73         default:
74           fprintf (stdout, "\n");
75           break;
76         }
77     }
78 }
79
80 static void
81 dump_attrs (Repo *repo, unsigned int entry)
82 {
83   unsigned i;
84   for (i = 0; i < repo->nrepodata; i++)
85     {
86       Attrstore *s = repo->repodata[i].s;
87       if (s && entry < s->entries)
88         dump_attrs_1 (s, entry);
89     }
90 }
91 #endif
92
93 static void
94 dump_repodata (Repo *repo)
95 {
96   unsigned i;
97   Repodata *data;
98   if (repo->nrepodata == 0)
99     return;
100   printf("repo refers to %d subfiles:\n", repo->nrepodata);
101   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
102     {
103       unsigned int j;
104       printf("%s has %d keys", data->location ? data->location : "**EMBED**", data->nkeys);
105       for (j = 1; j < data->nkeys; j++)
106         printf("\n  %s", id2str(repo->pool, data->keys[j].name));
107       printf("\n");
108     }
109   printf("\n");
110 }
111
112 static void
113 printids(Repo *repo, char *kind, Offset ido)
114 {
115   Pool *pool = repo->pool;
116   Id id, *ids;
117   if (!ido)
118     return;
119   printf("%s:\n", kind);
120   ids = repo->idarraydata + ido;
121   while((id = *ids++) != 0)
122     printf("  %s\n", dep2str(pool, id));
123 }
124
125 static void
126 printdir(Repodata *data, Id dir)
127 {
128   Id comp;
129   Id parent = dirpool_parent(&data->dirpool, dir);
130   if (parent)
131     {
132       printdir(data, parent);
133       putchar('/');
134     }
135   comp = dirpool_compid(&data->dirpool, dir);
136   if (data->localpool)
137     printf("%s", stringpool_id2str(&data->spool, comp));
138   else
139     printf("%s", id2str(data->repo->pool, comp));
140 }
141
142 int
143 dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv)
144 {
145   const char *keyname;
146
147   keyname = id2str(data->repo->pool, key->name);
148   switch(key->type)
149     {
150     case TYPE_ID:
151       if (data->localpool)
152         kv->str = stringpool_id2str(&data->spool, kv->id);
153       else
154         kv->str = id2str(data->repo->pool, kv->id);
155       printf("%s: %s\n", keyname, kv->str);
156       break;
157     case TYPE_STR:
158       printf("%s: %s\n", keyname, kv->str);
159       break;
160     case TYPE_VOID:
161       printf("%s\n", keyname);
162       break;
163     case TYPE_NUM:
164     case TYPE_CONSTANT:
165       printf("%s: %d\n", keyname, kv->num);
166       break;
167     case TYPE_DIRNUMNUMARRAY:
168       printf("%s: ", keyname);
169       printdir(data, kv->id);
170       printf(" %d %d\n", kv->num, kv->num2);
171       break;
172     default:
173       printf("%s: ?\n", keyname);
174       break;
175     }
176   return 0;
177 }
178
179 void
180 dump_repoattrs(Repo *repo, Id p)
181 {
182   int i;
183   Repodata *data;
184   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
185     {
186       if (data->state == REPODATA_STUB || data->state == REPODATA_ERROR)
187         continue;
188       if (p < data->start || p >= data->end)
189         continue;
190       repodata_search(data, p - data->start, 0, dump_repoattrs_cb, 0);
191     }
192 }
193
194 void
195 dump_some_attrs(Repo *repo, Solvable *s)
196 {
197   Id name = str2id (repo->pool, "summary", 0);
198   const char *summary = 0;
199   unsigned int medianr = -1, downloadsize = -1;
200   unsigned int time = -1;
201   if (name)
202     summary = repo_lookup_str (s, name);
203   if ((name = str2id (repo->pool, "medianr", 0)))
204     medianr = repo_lookup_num (s, name);
205   if ((name = str2id (repo->pool, "downloadsize", 0)))
206     downloadsize = repo_lookup_num (s, name);
207   if ((name = str2id (repo->pool, "time", 0)))
208     time = repo_lookup_num (s, name);
209
210   printf ("  XXX %d %d %u %s\n", medianr, downloadsize, time, summary);
211 }
212
213 static FILE *
214 loadcallback (Pool *pool, Repodata *data, void *vdata)
215 {
216   FILE *fp = 0;
217   fprintf (stderr, "Loading SOLV file %s\n", data->location);
218   if (attrname)
219     {
220       fp = fopen (attrname, "r");
221       if (!fp)
222         perror(attrname);
223     }
224   return fp;
225 }
226
227
228 static void
229 usage( const char *err )
230 {
231   if (err)
232     fprintf (stderr, "\n** Error:\n  %s\n", err);
233   fprintf( stderr, "\nUsage:\n"
234            "dumpsolv [-a] [-n <attrname>] [<solvfile>]\n"
235            "  -a            read attributes.\n"
236            "                If no attribute name (-n) is given,\n"
237            "                  it is deduced from the .solv name\n"
238            "                  by replacing '.solv' with '.attr'\n"
239            "                If neither an attribute name nor a solvfile are given,\n"
240            "                  the attribute name defaults to 'test.attr'\n"
241            "  -n <attrname> use <attrname> (evtl. suffixed by '.attr') for attributes\n"
242            );
243   exit(0);
244 }
245
246
247 int main(int argc, char **argv)
248 {
249   Repo *repo;
250   Pool *pool;
251   int i, n;
252   Solvable *s;
253   const char *solvname = 0;
254   
255   argv++;
256   argc--;
257   while (argc--)
258     {
259       const char *s = argv[0];
260       if (*s++ == '-')
261         while (*s)
262           switch (*s++)
263             {
264               case 'h': usage(NULL); break;
265               case 'a':
266                 if (!attrname)
267                   attrname = "";
268                 break;
269               case 'n':
270                 if (argc)
271                   {
272                     attrname = argv[1];
273                     argv++;
274                     argc--;
275                   }
276                 else
277                   usage("argument required for '-n'");
278                 break;
279               default : break;
280             }
281       else
282         {
283           solvname = argv[0];
284           if (freopen (solvname, "r", stdin) == 0)
285             {
286               perror(solvname);
287               exit(1);
288             }
289           break;
290         }
291       argv++;
292     }
293
294   if (attrname) /* attributes wanted */
295     {
296       if (*attrname == 0) /* no attrname given */
297       {
298         if (solvname) /* solvname given -> deduce attrname from it */
299         {
300           attrname = strdup (solvname);
301           char *dot = strrchr(attrname, '.');
302           if (dot && !strcmp(dot, ".solv")) /* if it ends in .solv, just keep the dot */
303             dot[1] = 0;
304         }
305         else
306           attrname = "test.attr"; /* default to "test.attr" */
307       }
308       
309       /* ensure '.attr' suffix */
310       const char *dot = strrchr(attrname, '.');
311       if (!dot || strcmp(dot, ".attr"))
312       {
313         int len = strlen (attrname);
314         char *newname = (char *)malloc (len + 6); /* alloc for <attrname>+'.attr'+'\0' */
315         strcpy (newname, attrname);
316         strcpy (newname+len, ".attr");
317         attrname = newname;
318       }
319     }
320
321   pool = pool_create();
322   pool_setdebuglevel(pool, 1);
323   pool_setloadcallback(pool, loadcallback, 0);
324
325   repo = repo_create(pool, argc != 1 ? argv[1] : "<stdin>");
326   if (repo_add_solv(repo, stdin))
327     printf("could not read repository\n");
328   dump_repodata (repo);
329   printf("repo contains %d solvables\n", repo->nsolvables);
330   for (i = repo->start, n = 1; i < repo->end; i++)
331     {
332       s = pool->solvables + i;
333       if (s->repo != repo)
334         continue;
335       printf("\n");
336       printf("solvable %d:\n", n);
337       if (s->name || s->evr || s->arch)
338         printf("name: %s(%s) %s %s\n", id2str(pool, s->name) + s->kind, id2str(pool, s->name), id2str(pool, s->evr), id2str(pool, s->arch));
339       if (s->vendor)
340         printf("vendor: %s\n", id2str(pool, s->vendor));
341       printids(repo, "provides", s->provides);
342       printids(repo, "obsoletes", s->obsoletes);
343       printids(repo, "conflicts", s->conflicts);
344       printids(repo, "requires", s->requires);
345       printids(repo, "recommends", s->recommends);
346       printids(repo, "suggests", s->suggests);
347       printids(repo, "supplements", s->supplements);
348       printids(repo, "enhances", s->enhances);
349       printids(repo, "freshens", s->freshens);
350 #if 0
351       dump_attrs (repo, n - 1);
352 #endif
353       dump_repoattrs(repo, i);
354 #if 1
355       dump_some_attrs(repo, s);
356 #endif
357       n++;
358     }
359   pool_free(pool);
360   exit(0);
361 }