make repodata_stringify return the result string
[platform/upstream/libsolv.git] / tools / susetags2solv.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 #define _GNU_SOURCE
9
10 #include <sys/types.h>
11 #include <limits.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <dirent.h>
17 #include <zlib.h>
18 #include <getopt.h>
19
20 #include "pool.h"
21 #include "repo.h"
22 #include "repo_solv.h"
23 #include "repo_susetags.h"
24 #include "repo_content.h"
25 #ifdef SUSE
26 #include "repo_autopattern.h"
27 #endif
28 #include "common_write.h"
29 #include "solv_xfopen.h"
30
31 static void
32 usage(int status)
33 {
34   fprintf(stderr, "\nUsage:\n"
35           "susetags2solv [-b <base>][-c <content>][-d <descrdir>][-h][-n <name>]\n"
36           "  reads a 'susetags' repository from <stdin> and writes a .solv file to <stdout>\n"
37           "  -b <base>: save as multiple files starting with <base>\n"
38           "  -c <contentfile> : parse given contentfile (for product information)\n"
39           "  -d <descrdir> : do not read from stdin, but use data in descrdir\n"
40           "  -h : print help & exit\n"
41           "  -n <name>: save attributes as <name>.attr\n"
42          );
43    exit(status);
44 }
45
46 /* content file query */
47 static void
48 doquery(Pool *pool, Repo *repo, const char *arg)
49 {
50   char qbuf[256];
51   const char *str;
52   Id id;
53
54   snprintf(qbuf, sizeof(qbuf), "susetags:%s", arg);
55   id = pool_str2id(pool, qbuf, 0);
56   if (!id)
57     return;
58   str = repo_lookup_str(repo, SOLVID_META, id);
59   if (str)
60     printf("%s\n", str);
61 }
62
63 int
64 main(int argc, char **argv)
65 {
66   const char *contentfile = 0;
67   const char *attrname = 0;
68   const char *descrdir = 0;
69   const char *basefile = 0;
70   const char *query = 0;
71   const char *mergefile = 0;
72   Id defvendor = 0;
73   int flags = 0;
74 #ifdef SUSE
75   int add_auto = 0;
76 #endif
77   int c;
78   Pool *pool;
79   Repo *repo;
80
81   while ((c = getopt(argc, argv, "hn:c:d:b:q:M:X")) >= 0)
82     {
83       switch (c)
84         {
85         case 'h':
86           usage(0);
87           break;
88         case 'n':
89           attrname = optarg;
90           break;
91         case 'c':
92           contentfile = optarg;
93           break;
94         case 'd':
95           descrdir = optarg;
96           break;
97         case 'b':
98           basefile = optarg;
99           break;
100         case 'q':
101           query = optarg;
102           break;
103         case 'M':
104           mergefile = optarg;
105           break;
106         case 'X':
107 #ifdef SUSE
108           add_auto = 1;
109 #endif
110           break;
111         default:
112           usage(1);
113           break;
114         }
115     }
116   pool = pool_create();
117   repo = repo_create(pool, "<susetags>");
118
119   repo_add_repodata(repo, 0);
120
121   if (contentfile)
122     {
123       FILE *fp = fopen(contentfile, "r");
124       if (!fp)
125         {
126           perror(contentfile);
127           exit(1);
128         }
129       if (repo_add_content(repo, fp, REPO_REUSE_REPODATA))
130         {
131           fprintf(stderr, "susetags2solv: %s: %s\n", contentfile, pool_errstr(pool));
132           exit(1);
133         }
134       defvendor = repo_lookup_id(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR);
135       fclose(fp);
136     }
137
138   if (attrname)
139     {
140       /* ensure '.attr' suffix */
141       const char *dot = strrchr(attrname, '.');
142       if (!dot || strcmp(dot, ".attr"))
143       {
144         int len = strlen (attrname);
145         char *newname = (char *)malloc(len + 6); /* alloc for <attrname>+'.attr'+'\0' */
146         strcpy (newname, attrname);
147         strcpy (newname+len, ".attr");
148         attrname = newname;
149       }
150     }
151
152   /*
153    * descrdir path given, open files and read from there
154    */
155   
156   if (descrdir)
157     {
158       char *fnp;
159       int ndirs, i;
160       struct dirent **files;
161
162       ndirs = scandir(descrdir, &files, 0, alphasort);
163       if (ndirs < 0)
164         {
165           perror(descrdir);
166           exit(1);
167         }
168
169       /* bring packages to front */
170       for (i = 0; i < ndirs; i++)
171         {
172           char *fn = files[i]->d_name;
173           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
174             break;
175         }
176       if (i == ndirs)
177         {
178           fprintf(stderr, "found no packages file\n");
179           exit(1);
180         }
181       if (i)
182         {
183           struct dirent *de = files[i];
184           memmove(files + 1, files, i * sizeof(de));
185           files[0] = de;
186         }
187
188       fnp = solv_malloc(strlen(descrdir) + 128);
189       for (i = 0; i < ndirs; i++)
190         {
191           char *fn = files[i]->d_name;
192
193           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
194             {
195               FILE *fp;
196               sprintf(fnp, "%s/%s", descrdir, fn);
197               fp = solv_xfopen(fnp, 0);
198               if (!fp)
199                 {
200                   perror(fn);
201                   exit(1);
202                 }
203               if (repo_add_susetags(repo, fp, defvendor, 0, flags | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
204                 {
205                   fprintf(stderr, "susetags2solv: %s: %s\n", fnp, pool_errstr(pool));
206                   exit(1);
207                 }
208               fclose(fp);
209             }
210           else if (!strcmp(fn, "packages.DU") || !strcmp(fn, "packages.DU.gz"))
211             {
212               FILE *fp;
213               sprintf(fnp, "%s/%s", descrdir, fn);
214               fp = solv_xfopen(fnp, 0);
215               if (!fp)
216                 {
217                   perror(fn);
218                   exit(1);
219                 }
220               if (repo_add_susetags(repo, fp, defvendor, 0, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
221                 {
222                   fprintf(stderr, "susetags2solv: %s: %s\n", fnp, pool_errstr(pool));
223                   exit(1);
224                 }
225               fclose(fp);
226             }
227           else if (!strcmp(fn, "packages.FL") || !strcmp(fn, "packages.FL.gz"))
228             {
229 #if 0
230               sprintf(fnp, "%s/%s", descrdir, fn);
231               FILE *fp = solv_xfopen(fnp, 0);
232               if (!fp)
233                 {
234                   perror(fn);
235                   exit(1);
236                 }
237               if (repo_add_susetags(repo, fp, defvendor, 0, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
238                 {
239                   fprintf(stderr, "susetags2solv: %s: %s\n", fnp, pool_errstr(pool));
240                   exit(1);
241                 }
242               fclose(fp);
243 #else
244               /* ignore for now. reactivate when filters work */
245               continue;
246 #endif
247             }
248           else if (!strncmp(fn, "packages.", 9))
249             {
250               char lang[6];
251               char *p;
252               FILE *fp;
253               sprintf(fnp, "%s/%s", descrdir, fn);
254               p = strrchr(fnp, '.');
255               if (p && !strcmp(p, ".gz"))
256                 {
257                   *p = 0;
258                   p = strrchr(fnp, '.');
259                 }
260               if (!p || !p[1] || strlen(p + 1) > 5)
261                 continue;
262               strcpy(lang, p + 1);
263               sprintf(fnp, "%s/%s", descrdir, fn);
264               fp = solv_xfopen(fnp, 0);
265               if (!fp)
266                 {
267                   perror(fn);
268                   exit(1);
269                 }
270               if (repo_add_susetags(repo, fp, defvendor, lang, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
271                 {
272                   fprintf(stderr, "susetags2solv: %s: %s\n", fnp, pool_errstr(pool));
273                   exit(1);
274                 }
275               fclose(fp);
276             }
277         }
278       for (i = 0; i < ndirs; i++)
279         free(files[i]);
280       free(files);
281       free(fnp);
282       repo_internalize(repo);
283     }
284   else
285     {
286       /* read data from stdin */
287       if (repo_add_susetags(repo, stdin, defvendor, 0, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE))
288         {
289           fprintf(stderr, "susetags2solv: %s\n", pool_errstr(pool));
290           exit(1);
291         }
292     }
293   repo_internalize(repo);
294   if (mergefile)
295     {
296       FILE *fp = fopen(mergefile, "r");
297       if (!fp)
298         {
299           perror(mergefile);
300           exit(1);
301         }
302       if (repo_add_solv(repo, fp, 0))
303         {
304           fprintf(stderr, "susetags2solv: %s\n", pool_errstr(pool));
305           exit(1);
306         }
307       fclose(fp);
308     }
309 #ifdef SUSE
310   if (add_auto)
311     repo_add_autopattern(repo, 0); 
312 #endif
313
314   if (query)
315     doquery(pool, repo, query);
316   else
317     tool_write(repo, basefile, attrname);
318   pool_free(pool);
319   exit(0);
320 }