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