missing solvable_lookup_bool implementation
[platform/upstream/libsolv.git] / src / solvable.c
1 /*
2  * Copyright (c) 2008, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 /*
9  * solvable.c
10  *
11  * set/retrieve data from solvables
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <unistd.h>
18 #include <string.h>
19
20 #include "pool.h"
21 #include "repo.h"
22 #include "util.h"
23
24 const char *
25 solvable2str(Pool *pool, Solvable *s)
26 {
27   const char *n, *e, *a;
28   char *p;
29   n = id2str(pool, s->name);
30   e = id2str(pool, s->evr);
31   a = id2str(pool, s->arch);
32   p = pool_alloctmpspace(pool, strlen(n) + strlen(e) + strlen(a) + 3);
33   sprintf(p, "%s-%s.%s", n, e, a);
34   return p;
35 }
36
37 Id
38 solvable_lookup_id(Solvable *s, Id keyname)
39 {
40   Repo *repo = s->repo;
41   Pool *pool;
42   Repodata *data;
43   int i, j, n;
44
45   if (!repo)
46     return 0;
47   pool = repo->pool;
48   switch(keyname)
49     {
50     case SOLVABLE_NAME:
51       return s->name;
52     case SOLVABLE_ARCH:
53       return s->arch;
54     case SOLVABLE_EVR:
55       return s->evr;
56     case SOLVABLE_VENDOR:
57       return s->vendor;
58     }
59   n = s - pool->solvables;
60   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
61     {
62       if (n < data->start || n >= data->end)
63         continue;
64       for (j = 1; j < data->nkeys; j++)
65         {
66           if (data->keys[j].name == keyname && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID))
67             {
68               Id id = repodata_lookup_id(data, n - data->start, j);
69               if (id)
70                 {
71                   if (data->localpool)
72                     id = repodata_globalize_id(data, id);
73                   return id;
74                 }
75             }
76         }
77     }
78   return 0;
79 }
80
81 const char *
82 solvable_lookup_str(Solvable *s, Id keyname)
83 {
84   Repo *repo = s->repo;
85   Pool *pool;
86   Repodata *data;
87   int i, j, n;
88   const char *str;
89
90   if (!repo)
91     return 0;
92   pool = repo->pool;
93   switch(keyname)
94     {
95     case SOLVABLE_NAME:
96       return id2str(pool, s->name);
97     case SOLVABLE_ARCH:
98       return id2str(pool, s->arch);
99     case SOLVABLE_EVR:
100       return id2str(pool, s->evr);
101     case SOLVABLE_VENDOR:
102       return id2str(pool, s->vendor);
103     }
104   n = s - pool->solvables;
105   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
106     {
107       if (n < data->start || n >= data->end)
108         continue;
109       for (j = 1; j < data->nkeys; j++)
110         {
111           if (data->keys[j].name == keyname && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID || data->keys[j].type == REPOKEY_TYPE_STR))
112             {
113               str = repodata_lookup_str(data, n - data->start, j);
114               if (str)
115                 return str;
116             }
117         }
118     }
119   return 0;
120 }
121
122 const char *
123 solvable_lookup_str_poollang(Solvable *s, Id keyname)
124 {
125   Pool *pool;
126   int i, cols;
127   const char *str;
128   Id *row;
129
130   if (!s->repo)
131     return repo_lookup_str(s, keyname);
132   pool = s->repo->pool;
133   if (!pool->nlanguages)
134     return repo_lookup_str(s, keyname);
135   cols = pool->nlanguages + 1;
136   if (!pool->languagecache)
137     {
138       pool->languagecache = sat_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
139       pool->languagecacheother = 0;
140     }
141   if (keyname >= ID_NUM_INTERNAL)
142     {
143       row = pool->languagecache + ID_NUM_INTERNAL * cols;
144       for (i = 0; i < pool->languagecacheother; i++, row += cols)
145         if (*row == keyname)
146           break;
147       if (i >= pool->languagecacheother)
148         {
149           pool->languagecache = sat_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
150           pool->languagecacheother++;
151           row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
152         }
153     }
154   else
155     row = pool->languagecache + keyname * cols;
156   row++;        /* skip keyname */
157   for (i = 0; i < pool->nlanguages; i++, row++)
158     {
159       if (!*row)
160         {
161           char *p;
162           const char *kn;
163
164           kn = id2str(pool, keyname);
165           p = sat_malloc(strlen(kn) + strlen(pool->languages[i]) + 2);
166           sprintf(p, "%s:%s", kn, pool->languages[i]);
167           *row = str2id(pool, p, 1);
168           sat_free(p);
169         }
170       str = repo_lookup_str(s, *row);
171       if (str)
172         return str;
173     }
174   return repo_lookup_str(s, keyname);
175 }
176
177 const char *
178 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang)
179 {
180   Pool *pool;
181   Id id;
182   char *p;
183   const char *kn, *str;
184
185   if (!s->repo)
186     return repo_lookup_str(s, keyname);
187   pool = s->repo->pool;
188   kn = id2str(pool, keyname);
189   p = sat_malloc(strlen(kn) + strlen(lang) + 2);
190   sprintf(p, "%s:%s", kn, lang);
191   id = str2id(pool, p, 0);
192   if (id)
193     {
194       str = repo_lookup_str(s, id);
195       if (str)
196         return str;
197     }
198   return repo_lookup_str(s, keyname);
199 }
200
201 unsigned int
202 solvable_lookup_num(Solvable *s, Id keyname, unsigned int notfound)
203 {
204   Repo *repo = s->repo;
205   Pool *pool;
206   Repodata *data;
207   int i, j, n;
208
209   if (!repo)
210     return 0;
211   pool = repo->pool;
212   if (keyname == RPM_RPMDBID)
213     {
214       if (repo->rpmdbid)
215         return repo->rpmdbid[(s - pool->solvables) - repo->start];
216       return notfound;
217     }
218   n = s - pool->solvables;
219   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
220     {
221       if (n < data->start || n >= data->end)
222         continue;
223       for (j = 1; j < data->nkeys; j++)
224         {
225           if (data->keys[j].name == keyname
226               && (data->keys[j].type == REPOKEY_TYPE_U32
227                   || data->keys[j].type == REPOKEY_TYPE_NUM
228                   || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
229             {
230               unsigned int value;
231               if (repodata_lookup_num(data, n - data->start, j, &value))
232                 return value;
233             }
234         }
235     }
236   return notfound;
237 }
238
239 int
240 solvable_lookup_bool(Solvable *s, Id keyname)
241 {
242   return solvable_lookup_num(s, keyname, 0) ? 1 : 0;
243 }
244
245 int
246 solvable_lookup_void(Solvable *s, Id keyname)
247 {
248   Repo *repo = s->repo;
249   Pool *pool;
250   Repodata *data;
251   int i, j, n;
252
253   if (!repo)
254     return 0;
255   pool = repo->pool;
256   n = s - pool->solvables;
257   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
258     {
259       if (n < data->start || n >= data->end)
260         continue;
261       for (j = 1; j < data->nkeys; j++)
262         {
263           if (data->keys[j].name == keyname
264               && (data->keys[j].type == REPOKEY_TYPE_VOID))
265             {
266               if (repodata_lookup_void(data, n - data->start, j))
267                 return 1;
268             }
269         }
270     }
271   return 0;
272 }
273
274 const unsigned char *
275 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
276 {
277   Repo *repo = s->repo;
278   Pool *pool;
279   Repodata *data;
280   int i, j, n;
281
282   *typep = 0;
283   if (!repo)
284     return 0;
285   pool = repo->pool;
286   n = s - pool->solvables;
287   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
288     {
289       if (n < data->start || n >= data->end)
290         continue;
291       for (j = 1; j < data->nkeys; j++)
292         {
293           if (data->keys[j].name == keyname
294               && (data->keys[j].type == REPOKEY_TYPE_MD5
295                   || data->keys[j].type == REPOKEY_TYPE_SHA1
296                   || data->keys[j].type == REPOKEY_TYPE_SHA256))
297             {
298               const unsigned char *chk = repodata_lookup_bin_checksum(data, n - data->start, j, typep);
299               if (chk)
300                 return chk;
301             }
302         }
303     }
304   return 0;
305 }
306
307 const char *
308 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
309 {
310   const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
311   /* we need the repodata just as a reference for a pool */
312   return chk ? repodata_chk2str(s->repo->repodata, *typep, chk) : 0;
313 }
314
315 char *
316 solvable_get_location(Solvable *s, unsigned int *medianrp)
317 {
318   Pool *pool;
319   int l = 0;
320   char *loc;
321   const char *mediadir, *mediafile;
322
323   *medianrp = 0;
324   if (!s->repo)
325     return 0;
326   pool = s->repo->pool;
327   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
328   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
329     mediadir = id2str(pool, s->arch);
330   else
331     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
332   if (mediadir)
333     l = strlen(mediadir) + 1;
334   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
335     {
336       const char *name, *evr, *arch;
337       name = id2str(pool, s->name);
338       evr = id2str(pool, s->evr);
339       arch = id2str(pool, s->arch);
340       /* name-evr.arch.rpm */
341       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
342       if (mediadir)
343         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
344       else
345         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
346     }
347   else
348     {
349       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
350       if (!mediafile)
351         return 0;
352       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
353       if (mediadir)
354         sprintf(loc, "%s/%s", mediadir, mediafile);
355       else
356         strcpy(loc, mediafile);
357     }
358   return loc;
359 }