2b926bb33de299cfabce4198bcca95c932f9b234
[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 "sat_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 = 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
71   while ((c = getopt(argc, argv, "hn:c:d:b:q:")) >= 0)
72     {
73       switch (c)
74         {
75         case 'h':
76           usage(0);
77           break;
78         case 'n':
79           attrname = optarg;
80           break;
81         case 'c':
82           contentfile = optarg;
83           break;
84         case 'd':
85           descrdir = optarg;
86           break;
87         case 'b':
88           basefile = optarg;
89           break;
90         case 'q':
91           query = optarg;
92           break;
93         default:
94           usage(1);
95           break;
96         }
97     }
98   Pool *pool = pool_create();
99   Repo *repo = repo_create(pool, "<susetags>");
100
101   repo_add_repodata(repo, 0);
102
103   if (contentfile)
104     {
105       FILE *fp = fopen(contentfile, "r");
106       if (!fp)
107         {
108           perror(contentfile);
109           exit(1);
110         }
111       repo_add_content(repo, fp, REPO_REUSE_REPODATA);
112       defvendor = repo_lookup_id(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR);
113       fclose(fp);
114     }
115
116   if (attrname)
117     {
118       /* ensure '.attr' suffix */
119       const char *dot = strrchr(attrname, '.');
120       if (!dot || strcmp(dot, ".attr"))
121       {
122         int len = strlen (attrname);
123         char *newname = (char *)malloc(len + 6); /* alloc for <attrname>+'.attr'+'\0' */
124         strcpy (newname, attrname);
125         strcpy (newname+len, ".attr");
126         attrname = newname;
127       }
128     }
129
130   /*
131    * descrdir path given, open files and read from there
132    */
133   
134   if (descrdir)
135     {
136       char *fnp;
137       int ndirs, i;
138       struct dirent **files;
139
140       ndirs = scandir(descrdir, &files, 0, alphasort);
141       if (ndirs < 0)
142         {
143           perror(descrdir);
144           exit(1);
145         }
146
147       /* bring packages to front */
148       for (i = 0; i < ndirs; i++)
149         {
150           char *fn = files[i]->d_name;
151           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
152             break;
153         }
154       if (i == ndirs)
155         {
156           fprintf(stderr, "found no packages file\n");
157           exit(1);
158         }
159       if (i)
160         {
161           struct dirent *de = files[i];
162           memmove(files + 1, files, i * sizeof(de));
163           files[0] = de;
164         }
165
166       fnp = sat_malloc(strlen(descrdir) + 128);
167       for (i = 0; i < ndirs; i++)
168         {
169           char *fn = files[i]->d_name;
170
171           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
172             {
173               sprintf(fnp, "%s/%s", descrdir, fn);
174               FILE *fp = sat_xfopen(fnp);
175               if (!fp)
176                 {
177                   perror(fn);
178                   exit(1);
179                 }
180               repo_add_susetags(repo, fp, defvendor, 0, flags | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
181               fclose(fp);
182             }
183           else if (!strcmp(fn, "packages.DU") || !strcmp(fn, "packages.DU.gz"))
184             {
185               sprintf(fnp, "%s/%s", descrdir, fn);
186               FILE *fp = sat_xfopen(fnp);
187               if (!fp)
188                 {
189                   perror(fn);
190                   exit(1);
191                 }
192               repo_add_susetags(repo, fp, defvendor, 0, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
193               fclose(fp);
194             }
195           else if (!strcmp(fn, "packages.FL") || !strcmp(fn, "packages.FL.gz"))
196             {
197 #if 0
198               sprintf(fnp, "%s/%s", descrdir, fn);
199               FILE *fp = sat_xfopen(fnp);
200               if (!fp)
201                 {
202                   perror(fn);
203                   exit(1);
204                 }
205               repo_add_susetags(repo, fp, defvendor, 0, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
206               fclose(fp);
207 #else
208               /* ignore for now. reactivate when filters work */
209               continue;
210 #endif
211             }
212           else if (!strncmp(fn, "packages.", 9))
213             {
214               char lang[6];
215               char *p;
216               sprintf(fnp, "%s/%s", descrdir, fn);
217               p = strrchr(fnp, '.');
218               if (p && !strcmp(p, ".gz"))
219                 {
220                   *p = 0;
221                   p = strrchr(fnp, '.');
222                 }
223               if (!p || !p[1] || strlen(p + 1) > 5)
224                 continue;
225               strcpy(lang, p + 1);
226               sprintf(fnp, "%s/%s", descrdir, fn);
227               FILE *fp = sat_xfopen(fnp);
228               if (!fp)
229                 {
230                   perror(fn);
231                   exit(1);
232                 }
233               repo_add_susetags(repo, fp, defvendor, lang, flags | SUSETAGS_EXTEND | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
234               fclose(fp);
235             }
236         }
237       for (i = 0; i < ndirs; i++)
238         free(files[i]);
239       free(files);
240       free(fnp);
241       repo_internalize(repo);
242     }
243   else
244     /* read data from stdin */
245     repo_add_susetags(repo, stdin, defvendor, 0, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE);
246   repo_internalize(repo);
247
248   if (query)
249     doquery(pool, repo, query);
250   else
251     tool_write(repo, basefile, attrname);
252   pool_free(pool);
253   exit(0);
254 }