- add lookup_id function
[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_void(Solvable *s, Id keyname)
241 {
242   Repo *repo = s->repo;
243   Pool *pool;
244   Repodata *data;
245   int i, j, n;
246
247   if (!repo)
248     return 0;
249   pool = repo->pool;
250   n = s - pool->solvables;
251   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
252     {
253       if (n < data->start || n >= data->end)
254         continue;
255       for (j = 1; j < data->nkeys; j++)
256         {
257           if (data->keys[j].name == keyname
258               && (data->keys[j].type == REPOKEY_TYPE_VOID))
259             {
260               if (repodata_lookup_void(data, n - data->start, j))
261                 return 1;
262             }
263         }
264     }
265   return 0;
266 }
267
268 const unsigned char *
269 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
270 {
271   Repo *repo = s->repo;
272   Pool *pool;
273   Repodata *data;
274   int i, j, n;
275
276   *typep = 0;
277   if (!repo)
278     return 0;
279   pool = repo->pool;
280   n = s - pool->solvables;
281   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
282     {
283       if (n < data->start || n >= data->end)
284         continue;
285       for (j = 1; j < data->nkeys; j++)
286         {
287           if (data->keys[j].name == keyname
288               && (data->keys[j].type == REPOKEY_TYPE_MD5
289                   || data->keys[j].type == REPOKEY_TYPE_SHA1
290                   || data->keys[j].type == REPOKEY_TYPE_SHA256))
291             {
292               const unsigned char *chk = repodata_lookup_bin_checksum(data, n - data->start, j, typep);
293               if (chk)
294                 return chk;
295             }
296         }
297     }
298   return 0;
299 }
300
301 const char *
302 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
303 {
304   const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
305   /* we need the repodata just as a reference for a pool */
306   return chk ? repodata_chk2str(s->repo->repodata, *typep, chk) : 0;
307 }
308
309 char *
310 solvable_get_location(Solvable *s, unsigned int *medianrp)
311 {
312   Pool *pool;
313   int l = 0;
314   char *loc;
315   const char *mediadir, *mediafile;
316
317   *medianrp = 0;
318   if (!s->repo)
319     return 0;
320   pool = s->repo->pool;
321   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
322   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
323     mediadir = id2str(pool, s->arch);
324   else
325     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
326   if (mediadir)
327     l = strlen(mediadir) + 1;
328   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
329     {
330       const char *name, *evr, *arch;
331       name = id2str(pool, s->name);
332       evr = id2str(pool, s->evr);
333       arch = id2str(pool, s->arch);
334       /* name-evr.arch.rpm */
335       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
336       if (mediadir)
337         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
338       else
339         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
340     }
341   else
342     {
343       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
344       if (!mediafile)
345         return 0;
346       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
347       if (mediadir)
348         sprintf(loc, "%s/%s", mediadir, mediafile);
349       else
350         strcpy(loc, mediafile);
351     }
352   return loc;
353 }