prepare for parsing 'installed' products
[platform/upstream/libsolv.git] / tools / repo_products.c
1 /*
2  * repo_products.c
3  * 
4  * Parses all files below 'proddir'
5  * See http://en.opensuse.org/Product_Management/Code11
6  * 
7  * 
8  * Copyright (c) 2007, Novell Inc.
9  *
10  * This program is licensed under the BSD license, read LICENSE.BSD
11  * for further information
12  */
13
14 #include <sys/types.h>
15 #include <limits.h>
16 #include <fcntl.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21 #include <dirent.h>
22
23 #include "pool.h"
24 #include "repo.h"
25 #include "util.h"
26 #include "repo_content.h"
27
28 struct parsedata {
29   Repo *repo;
30   char *tmp;
31   int tmpl;
32 };
33
34
35
36 #if 0
37 /*
38  * split l into m parts, store to sp[]
39  *  split at whitespace
40  */
41
42 static int
43 split(char *l, char **sp, int m)
44 {
45   int i;
46   for (i = 0; i < m;)
47     {
48       while (*l == ' ' || *l == '\t')
49         l++;
50       if (!*l)
51         break;
52       sp[i++] = l;
53       if (i == m)
54         break;
55       while (*l && !(*l == ' ' || *l == '\t'))
56         l++;
57       if (!*l)
58         break;
59       *l++ = 0;
60     }
61   return i;
62 }
63
64
65 static Id
66 makeevr(Pool *pool, char *s)
67 {
68   if (!strncmp(s, "0:", 2) && s[2])
69     s += 2;
70   return str2id(pool, s, 1);
71 }
72
73 /*
74  * dependency relations
75  */
76
77 static char *flagtab[] = {
78   ">",
79   "=",
80   ">=",
81   "<",
82   "!=",
83   "<="
84 };
85 #endif
86
87 /*
88  * join up to three strings into one
89  */
90
91 static char *
92 join(struct parsedata *pd, const char *s1, const char *s2, const char *s3)
93 {
94   int l = 1;
95   char *p;
96
97   if (s1)
98     l += strlen(s1);
99   if (s2)
100     l += strlen(s2);
101   if (s3)
102     l += strlen(s3);
103   if (l > pd->tmpl)
104     {
105       pd->tmpl = l + 256;
106       pd->tmp = sat_realloc(pd->tmp, pd->tmpl);
107     }
108   p = pd->tmp;
109   if (s1)
110     {
111       strcpy(p, s1);
112       p += strlen(s1);
113     }
114   if (s2)
115     {
116       strcpy(p, s2);
117       p += strlen(s2);
118     }
119   if (s3)
120     {
121       strcpy(p, s3);
122       p += strlen(s3);
123     }
124   return pd->tmp;
125 }
126
127
128 #if 0
129 /*
130  * add dependency to pool
131  */
132
133 static unsigned int
134 adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, char *line, Id marker)
135 {
136   int flags, words;
137   Id id, evrid;
138   char *sp[4];
139
140   words = 0;
141   while (1)
142     {
143       /* Name [relop evr] [rest] --> 1, 2, 3 or 4 fields.  */
144       if ( line )
145         {
146           words += split(line, sp + words, 4 - words);
147           line = 0;
148         }
149       /* Hack, as the content file adds 'package:' for package
150          dependencies sometimes.  */
151       if (!strncmp (sp[0], "package:", 8))
152         sp[0] += 8;
153       id = str2id(pool, sp[0], 1);
154       if (words >= 3 && strpbrk (sp[1], "<>="))
155         {
156           evrid = makeevr(pool, sp[2]);
157           for (flags = 0; flags < 6; flags++)
158             if (!strcmp(sp[1], flagtab[flags]))
159               break;
160           if (flags == 6)
161             {
162               fprintf(stderr, "Unknown relation '%s'\n", sp[1]);
163               exit(1);
164             }
165           id = rel2id(pool, id, evrid, flags + 1, 1);
166           /* Consume three words, there's nothing to move to front.  */
167           if (words == 4)
168             line = sp[3];
169           words = 0;
170         }
171       else
172         {
173           int j;
174           /* Consume one word.  If we had more move them to front.  */
175           words--;
176           for (j = 0; j < words; j++)
177             sp[j] = sp[j+1];
178           if (words == 3)
179             line = sp[2], words = 2;
180         }
181       olddeps = repo_addid_dep(pd->repo, olddeps, id, marker);
182       if (! ( line || words > 0 ) )
183         break;
184     }
185   return olddeps;
186 }
187
188
189 /*
190  * split value and add to pool
191  */
192
193 static void
194 add_multiple_strings(Repodata *data, Id handle, Id name, char *value)
195 {
196   char *sp[2];
197   while (value)
198     {
199       int words = split(value, sp, 2);
200       if (!words)
201         break;
202       repodata_add_poolstr_array(data, handle, name, sp[0]);
203       if (words == 1)
204         break;
205       value = sp[1];
206     }
207 }
208 #endif
209
210 /*
211  * add single product to repo
212  *
213  */
214
215 static void
216 repo_add_product(struct parsedata *pd, FILE *fp)
217 {
218 #if 0
219   Pool *pool = pd->repo->pool;
220   char *line, *linep;
221   int aline;
222   Solvable *s, *firsts = 0;
223   Id handle = 0;
224   
225   line = sat_malloc(1024);
226   aline = 1024;
227
228   linep = line;
229   s = 0;
230
231   for (;;)
232     {
233 /*      char *fields[2]; */
234       
235       /* read line into big-enough buffer */
236       if (linep - line + 16 > aline)
237         {
238           aline = linep - line;
239           line = sat_realloc(line, aline + 512);
240           linep = line + aline;
241           aline += 512;
242         }
243       if (!fgets(linep, aline - (linep - line), fp))
244         break;
245       linep += strlen(linep);
246       if (linep == line || linep[-1] != '\n')
247         continue;
248       *--linep = 0;
249       linep = line;
250       /* expect "key value" lines */
251       if (split (line, fields, 2) == 2)
252         {
253           char *key = fields[0];
254           char *value = fields[1];
255         }
256       else
257         fprintf (stderr, "malformed line: %s\n", line);
258     }
259
260   if (!s)
261     {
262       fprintf(stderr, "No product solvable created !\n");
263       exit(1);
264     }
265
266   if (!s->arch)
267     s->arch = ARCH_NOARCH;
268   if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
269     {
270       s->provides = repo_addid_dep(pd->repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
271     }
272   
273   sat_free(line);
274 #endif
275 }
276
277
278 /*
279  * read all .prod files from directory
280  * parse each one as a product
281  */
282
283 void
284 repo_add_products(Repo *repo, const char *proddir)
285 {
286   DIR *dir = opendir(proddir);
287   struct dirent *entry;
288   struct parsedata pd;
289   Repodata *data;
290   
291   memset(&pd, 0, sizeof(pd));
292   if (repo->nrepodata)
293     /* use last repodata */
294     data = repo->repodata + repo->nrepodata - 1;
295   else
296     data = repo_add_repodata(repo, 0);
297
298   pd.repo = repo;
299
300   if (!dir)
301     {
302       perror(proddir);
303       return;
304     }
305   
306   while ((entry = readdir(dir)))
307     {
308       const char *dot;
309       dot = strrchr( entry->d_name, '.' );
310       if (dot && strcmp(dot, ".prod") == 0)
311         {
312           char *fullpath = join(&pd, proddir, "/", entry->d_name);
313           FILE *fp = fopen(fullpath, "r");
314           if (!fp)
315             {
316               perror(fullpath);
317               break;
318             }
319           repo_add_product(&pd, fp);
320           fclose(fp);
321         }
322     }
323   if (pd.tmp)
324     sat_free(pd.tmp);
325   closedir(dir);
326 }