- rename str_lang to str_poollang
[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 const char *
38 solvable_lookup_str(Solvable *s, Id keyname)
39 {
40   Repo *repo = s->repo;
41   Pool *pool;
42   Repodata *data;
43   int i, j, n;
44   const char *str;
45
46   if (!repo)
47     return 0;
48   pool = repo->pool;
49   switch(keyname)
50     {   
51     case SOLVABLE_NAME:
52       return id2str(pool, s->name);
53     case SOLVABLE_ARCH:
54       return id2str(pool, s->arch);
55     case SOLVABLE_EVR:
56       return id2str(pool, s->evr);
57     case SOLVABLE_VENDOR:
58       return id2str(pool, s->vendor);
59     }   
60   n = s - pool->solvables;
61   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
62     {   
63       if (n < data->start || n >= data->end)
64         continue;
65       for (j = 1; j < data->nkeys; j++)
66         {
67           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))
68             {
69               str = repodata_lookup_str(data, n - data->start, j); 
70               if (str)
71                 return str;
72             }
73         }
74     }
75   return 0;
76 }
77
78 const char *
79 solvable_lookup_str_poollang(Solvable *s, Id keyname)
80 {
81   Pool *pool;
82   int i, cols;
83   const char *str;
84   Id *row;
85
86   if (!s->repo)
87     return repo_lookup_str(s, keyname);
88   pool = s->repo->pool;
89   if (!pool->nlanguages)
90     return repo_lookup_str(s, keyname);
91   cols = pool->nlanguages + 1;
92   if (!pool->languagecache)
93     {
94       pool->languagecache = sat_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
95       pool->languagecacheother = 0;
96     }
97   if (keyname >= ID_NUM_INTERNAL)
98     {
99       row = pool->languagecache + ID_NUM_INTERNAL * cols;
100       for (i = 0; i < pool->languagecacheother; i++, row += cols)
101         if (*row == keyname)
102           break;
103       if (i >= pool->languagecacheother)
104         {
105           pool->languagecache = sat_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
106           pool->languagecacheother++;
107           row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
108         }
109     }
110   else
111     row = pool->languagecache + keyname * cols;
112   row++;        /* skip keyname */
113   for (i = 0; i < pool->nlanguages; i++, row++)
114     {
115       if (!*row)
116         {
117           char *p;
118           const char *kn;
119
120           kn = id2str(pool, keyname);
121           p = sat_malloc(strlen(kn) + strlen(pool->languages[i]) + 2);
122           sprintf(p, "%s:%s", kn, pool->languages[i]);
123           *row = str2id(pool, p, 1);
124           sat_free(p);
125         }
126       str = repo_lookup_str(s, *row);
127       if (str)
128         return str;
129     }
130   return repo_lookup_str(s, keyname);
131 }
132
133 const char *
134 solvable_lookup_str_lang(Solvable *s, Id keyname, const char *lang)
135 {
136   Pool *pool;
137   Id id;
138   char *p;
139   const char *kn, *str;
140
141   if (!s->repo)
142     return repo_lookup_str(s, keyname);
143   pool = s->repo->pool;
144   kn = id2str(pool, keyname);
145   p = sat_malloc(strlen(kn) + strlen(lang) + 2);
146   sprintf(p, "%s:%s", kn, lang);
147   id = str2id(pool, p, 0);
148   if (id)
149     {
150       str = repo_lookup_str(s, id);
151       if (str)
152         return str;
153     }
154   return repo_lookup_str(s, keyname);
155 }
156
157 unsigned int
158 solvable_lookup_num(Solvable *s, Id keyname, unsigned int notfound)
159 {
160   Repo *repo = s->repo;
161   Pool *pool;
162   Repodata *data;
163   int i, j, n;
164
165   if (!repo)
166     return 0;
167   pool = repo->pool;
168   if (keyname == RPM_RPMDBID)
169     {
170       if (repo->rpmdbid)
171         return repo->rpmdbid[(s - pool->solvables) - repo->start];
172       return notfound;
173     }
174   n = s - pool->solvables;
175   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
176     {
177       if (n < data->start || n >= data->end)
178         continue;
179       for (j = 1; j < data->nkeys; j++)
180         {
181           if (data->keys[j].name == keyname
182               && (data->keys[j].type == REPOKEY_TYPE_U32
183                   || data->keys[j].type == REPOKEY_TYPE_NUM
184                   || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
185             {
186               unsigned int value;
187               if (repodata_lookup_num(data, n - data->start, j, &value))
188                 return value;
189             }
190         }
191     }
192   return notfound;
193 }
194
195 int
196 solvable_lookup_void(Solvable *s, Id keyname)
197 {
198   Repo *repo = s->repo;
199   Pool *pool;
200   Repodata *data;
201   int i, j, n;
202
203   if (!repo)
204     return 0;
205   pool = repo->pool;
206   n = s - pool->solvables;
207   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
208     {
209       if (n < data->start || n >= data->end)
210         continue;
211       for (j = 1; j < data->nkeys; j++)
212         {
213           if (data->keys[j].name == keyname
214               && (data->keys[j].type == REPOKEY_TYPE_VOID))
215             {
216               if (repodata_lookup_void(data, n - data->start, j))
217                 return 1;
218             }
219         }
220     }
221   return 0;
222 }
223
224 const unsigned char *
225 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
226 {
227   Repo *repo = s->repo;
228   Pool *pool;
229   Repodata *data;
230   int i, j, n;
231
232   *typep = 0;
233   if (!repo)
234     return 0;
235   pool = repo->pool;
236   n = s - pool->solvables;
237   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
238     {
239       if (n < data->start || n >= data->end)
240         continue;
241       for (j = 1; j < data->nkeys; j++)
242         {
243           if (data->keys[j].name == keyname
244               && (data->keys[j].type == REPOKEY_TYPE_MD5
245                   || data->keys[j].type == REPOKEY_TYPE_SHA1
246                   || data->keys[j].type == REPOKEY_TYPE_SHA256))
247             {
248               const unsigned char *chk = repodata_lookup_bin_checksum(data, n - data->start, j, typep);
249               if (chk)
250                 return chk;
251             }
252         }
253     }
254   return 0;
255 }
256
257 const char *
258 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
259 {
260   const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
261   /* we need the repodata just as a reference for a pool */
262   return chk ? repodata_chk2str(s->repo->repodata, *typep, chk) : 0;
263 }
264
265 char *
266 solvable_get_location(Solvable *s, unsigned int *medianrp)
267 {
268   Pool *pool;
269   int l = 0;
270   char *loc;
271   const char *mediadir, *mediafile;
272
273   *medianrp = 0;
274   if (!s->repo)
275     return 0;
276   pool = s->repo->pool;
277   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
278   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
279     mediadir = id2str(pool, s->arch);
280   else
281     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
282   if (mediadir)
283     l = strlen(mediadir) + 1;
284   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
285     {
286       const char *name, *evr, *arch;
287       name = id2str(pool, s->name);
288       evr = id2str(pool, s->evr);
289       arch = id2str(pool, s->arch);
290       /* name-evr.arch.rpm */
291       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
292       if (mediadir)
293         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
294       else
295         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
296     }
297   else
298     {
299       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
300       if (!mediafile)
301         return 0;
302       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
303       if (mediadir)
304         sprintf(loc, "%s/%s", mediadir, mediafile);
305       else
306         strcpy(loc, mediafile);
307     }
308   return loc;
309 }