- add checksum lookup functions
[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_lang(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 unsigned int
134 solvable_lookup_num(Solvable *s, Id keyname, unsigned int notfound)
135 {
136   Repo *repo = s->repo;
137   Pool *pool;
138   Repodata *data;
139   int i, j, n;
140
141   if (!repo)
142     return 0;
143   pool = repo->pool;
144   if (keyname == RPM_RPMDBID)
145     {
146       if (repo->rpmdbid)
147         return repo->rpmdbid[(s - pool->solvables) - repo->start];
148       return notfound;
149     }
150   n = s - pool->solvables;
151   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
152     {
153       if (n < data->start || n >= data->end)
154         continue;
155       for (j = 1; j < data->nkeys; j++)
156         {
157           if (data->keys[j].name == keyname
158               && (data->keys[j].type == REPOKEY_TYPE_U32
159                   || data->keys[j].type == REPOKEY_TYPE_NUM
160                   || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
161             {
162               unsigned int value;
163               if (repodata_lookup_num(data, n - data->start, j, &value))
164                 return value;
165             }
166         }
167     }
168   return notfound;
169 }
170
171 int
172 solvable_lookup_void(Solvable *s, Id keyname)
173 {
174   Repo *repo = s->repo;
175   Pool *pool;
176   Repodata *data;
177   int i, j, n;
178
179   if (!repo)
180     return 0;
181   pool = repo->pool;
182   n = s - pool->solvables;
183   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
184     {
185       if (n < data->start || n >= data->end)
186         continue;
187       for (j = 1; j < data->nkeys; j++)
188         {
189           if (data->keys[j].name == keyname
190               && (data->keys[j].type == REPOKEY_TYPE_VOID))
191             {
192               if (repodata_lookup_void(data, n - data->start, j))
193                 return 1;
194             }
195         }
196     }
197   return 0;
198 }
199
200 const unsigned char *
201 solvable_lookup_bin_checksum(Solvable *s, Id keyname, Id *typep)
202 {
203   Repo *repo = s->repo;
204   Pool *pool;
205   Repodata *data;
206   int i, j, n;
207
208   if (!repo)
209     return 0;
210   pool = repo->pool;
211   n = s - pool->solvables;
212   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
213     {
214       if (n < data->start || n >= data->end)
215         continue;
216       for (j = 1; j < data->nkeys; j++)
217         {
218           if (data->keys[j].name == keyname
219               && (data->keys[j].type == REPOKEY_TYPE_MD5
220                   || data->keys[j].type == REPOKEY_TYPE_SHA1
221                   || data->keys[j].type == REPOKEY_TYPE_SHA256))
222             {
223               const unsigned char *chk = repodata_lookup_bin_checksum(data, n - data->start, j, typep);
224               if (chk)
225                 return chk;
226             }
227         }
228     }
229   return 0;
230 }
231
232 const char *
233 solvable_lookup_checksum(Solvable *s, Id keyname, Id *typep)
234 {
235   const unsigned char *chk = solvable_lookup_bin_checksum(s, keyname, typep);
236   /* we need the repodata just as a reference for a pool */
237   return chk ? repodata_chk2str(s->repo->repodata, *typep, chk) : 0;
238 }
239
240 char *
241 solvable_get_location(Solvable *s, unsigned int *medianrp)
242 {
243   Pool *pool;
244   int l = 0;
245   char *loc;
246   const char *mediadir, *mediafile;
247
248   *medianrp = 0;
249   if (!s->repo)
250     return 0;
251   pool = s->repo->pool;
252   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
253   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
254     mediadir = id2str(pool, s->arch);
255   else
256     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
257   if (mediadir)
258     l = strlen(mediadir) + 1;
259   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
260     {
261       const char *name, *evr, *arch;
262       name = id2str(pool, s->name);
263       evr = id2str(pool, s->evr);
264       arch = id2str(pool, s->arch);
265       /* name-evr.arch.rpm */
266       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
267       if (mediadir)
268         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
269       else
270         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
271     }
272   else
273     {
274       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
275       if (!mediafile)
276         return 0;
277       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
278       if (mediadir)
279         sprintf(loc, "%s/%s", mediadir, mediafile);
280       else
281         strcpy(loc, mediafile);
282     }
283   return loc;
284 }