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