05c683268eb728d00303a6f7fa340342f3254b6a
[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
19 #include "pool.h"
20 #include "repo.h"
21 #include "repo_susetags.h"
22 #include "repo_content.h"
23 #include "common_write.h"
24
25 static void
26 usage(int status)
27 {
28   fprintf(stderr, "\nUsage:\n"
29           "susetags2solv [-a][-s][-c <content>][-h]\n"
30           "  reads a 'susetags' repository from <stdin> and writes a .solv file to <stdout>\n"
31           "  -c <contentfile> : parse given contentfile (for product information)\n"
32           "  -d <descrdir> : do not read from stdin, but use data in descrdir\n"
33           "  -h : print help & exit\n"
34           "  -k : don't mix kinds (experimental!)\n"
35           "  -b <base>: save fas multiple files starting with <base>\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 int
75 main(int argc, char **argv)
76 {
77   const char *contentfile = 0;
78   const char *attrname = 0;
79   const char *descrdir = 0;
80   const char *basefile = 0;
81   Id vendor = 0;
82   int flags = 0;
83   int c;
84
85   while ((c = getopt(argc, argv, "hkn:c:d:b:")) >= 0)
86     {
87       switch (c)
88         {
89         case 'h':
90           usage(0);
91           break;
92         case 'k':
93           flags |= SUSETAGS_KINDS_SEPARATELY;   /* do not use! */
94           break;
95         case 'n':
96           attrname = optarg;
97           break;
98         case 'c':
99           contentfile = optarg;
100           break;
101         case 'd':
102           descrdir = optarg;
103           break;
104         case 'b':
105           basefile = optarg;
106           break;
107         default:
108           usage(1);
109           break;
110         }
111     }
112   Pool *pool = pool_create();
113   Repo *repo = repo_create(pool, "<susetags>");
114   if (contentfile)
115     {
116       FILE *fp = fopen (contentfile, "r");
117       if (!fp)
118         {
119           perror(contentfile);
120           exit(1);
121         }
122       repo_add_content(repo, fp);
123       if (!strncmp (id2str(pool, pool->solvables[repo->start].name), "product:", 8))
124         vendor = pool->solvables[repo->start].vendor;
125       fclose (fp);
126     }
127   if (attrname)
128     {
129       /* ensure '.attr' suffix */
130       const char *dot = strrchr(attrname, '.');
131       if (!dot || strcmp(dot, ".attr"))
132       {
133         int len = strlen (attrname);
134         char *newname = (char *)malloc(len + 6); /* alloc for <attrname>+'.attr'+'\0' */
135         strcpy (newname, attrname);
136         strcpy (newname+len, ".attr");
137         attrname = newname;
138       }
139     }
140
141   if (descrdir)
142     {
143       char *fnp;
144       int ndirs, i;
145       struct dirent **files;
146
147       ndirs = scandir(descrdir, &files, 0, alphasort);
148       if (ndirs < 0)
149         {
150           perror(descrdir);
151           exit(1);
152         }
153
154       /* bring packages to front */
155       for (i = 0; i < ndirs; i++)
156         {
157           char *fn = files[i]->d_name;
158           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
159             break;
160         }
161       if (i == ndirs)
162         {
163           fprintf(stderr, "found no packages file\n");
164           exit(1);
165         }
166       if (i)
167         {
168           struct dirent *de = files[i];
169           memmove(files + 1, files, i * sizeof(de));
170           files[0] = de;
171         }
172
173       fnp = sat_malloc(strlen(descrdir) + 128);
174       for (i = 0; i < ndirs; i++)
175         {
176           char *fn = files[i]->d_name;
177
178           if (!strcmp(fn, "packages") || !strcmp(fn, "packages.gz"))
179             {
180               sprintf(fnp, "%s/%s", descrdir, fn);
181               FILE *fp = myfopen(fnp);
182               if (!fp)
183                 {
184                   perror(fn);
185                   exit(1);
186                 }
187               repo_add_susetags(repo, fp, vendor, 0, flags);
188               fclose(fp);
189             }
190           else if (!strcmp(fn, "packages.DU") || !strcmp(fn, "packages.DU.gz"))
191             {
192               sprintf(fnp, "%s/%s", descrdir, fn);
193               FILE *fp = myfopen(fnp);
194               if (!fp)
195                 {
196                   perror(fn);
197                   exit(1);
198                 }
199               repo_add_susetags(repo, fp, vendor, 0, flags | SUSETAGS_EXTEND);
200               fclose(fp);
201             }
202           else if (!strncmp(fn, "packages.", 9))
203             {
204               char lang[6];
205               char *p;
206               sprintf(fnp, "%s/%s", descrdir, fn);
207               p = strrchr(fnp, '.');
208               if (p && !strcmp(p, ".gz"))
209                 {
210                   *p = 0;
211                   p = strrchr(fnp, '.');
212                 }
213               if (!p || !p[1] || strlen(p + 1) > 5)
214                 continue;
215               strcpy(lang, p + 1);
216               sprintf(fnp, "%s/%s", descrdir, fn);
217               FILE *fp = myfopen(fnp);
218               if (!fp)
219                 {
220                   perror(fn);
221                   exit(1);
222                 }
223               repo_add_susetags(repo, fp, vendor, lang, flags | SUSETAGS_EXTEND);
224               fclose(fp);
225             }
226         }
227       for (i = 0; i < ndirs; i++)
228         free(files[i]);
229       free(files);
230       free(fnp);
231     }
232   else
233     repo_add_susetags(repo, stdin, vendor, 0, flags);
234
235   tool_write(repo, basefile, attrname);
236   pool_free(pool);
237   exit(0);
238 }