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