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