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