- clean up tmp space management
[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 char *
201 solvable_get_location(Solvable *s, unsigned int *medianrp)
202 {
203   Pool *pool;
204   int l = 0;
205   char *loc;
206   const char *mediadir, *mediafile;
207
208   *medianrp = 0;
209   if (!s->repo)
210     return 0;
211   pool = s->repo->pool;
212   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
213   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
214     mediadir = id2str(pool, s->arch);
215   else
216     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
217   if (mediadir)
218     l = strlen(mediadir) + 1;
219   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
220     {
221       const char *name, *evr, *arch;
222       name = id2str(pool, s->name);
223       evr = id2str(pool, s->evr);
224       arch = id2str(pool, s->arch);
225       /* name-evr.arch.rpm */
226       loc = pool_alloctmpspace(pool, l + strlen(name) + strlen(evr) + strlen(arch) + 7);
227       if (mediadir)
228         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
229       else
230         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
231     }
232   else
233     {
234       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
235       if (!mediafile)
236         return 0;
237       loc = pool_alloctmpspace(pool, l + strlen(mediafile) + 1);
238       if (mediadir)
239         sprintf(loc, "%s/%s", mediadir, mediafile);
240       else
241         strcpy(loc, mediafile);
242     }
243   return loc;
244 }