- fix mem leaks
[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 solvable_lookup_str(Solvable *s, Id keyname)
26 {
27   Repo *repo = s->repo;
28   Pool *pool;
29   Repodata *data;
30   int i, j, n;
31   const char *str;
32
33   if (!repo)
34     return 0;
35   pool = repo->pool;
36   switch(keyname)
37     {   
38     case SOLVABLE_NAME:
39       return id2str(pool, s->name);
40     case SOLVABLE_ARCH:
41       return id2str(pool, s->arch);
42     case SOLVABLE_EVR:
43       return id2str(pool, s->evr);
44     case SOLVABLE_VENDOR:
45       return id2str(pool, s->vendor);
46     }   
47   n = s - pool->solvables;
48   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
49     {   
50       if (n < data->start || n >= data->end)
51         continue;
52       for (j = 1; j < data->nkeys; j++)
53         {
54           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))
55             {
56               str = repodata_lookup_str(data, n - data->start, j); 
57               if (str)
58                 return str;
59             }
60         }
61     }
62   return 0;
63 }
64
65 const char *
66 solvable_lookup_str_lang(Solvable *s, Id keyname)
67 {
68   Pool *pool;
69   int i, cols;
70   const char *str;
71   Id *row;
72
73   if (!s->repo)
74     return repo_lookup_str(s, keyname);
75   pool = s->repo->pool;
76   if (!pool->nlanguages)
77     return repo_lookup_str(s, keyname);
78   cols = pool->nlanguages + 1;
79   if (!pool->languagecache)
80     {
81       pool->languagecache = sat_calloc(cols * ID_NUM_INTERNAL, sizeof(Id));
82       pool->languagecacheother = 0;
83     }
84   if (keyname >= ID_NUM_INTERNAL)
85     {
86       row = pool->languagecache + ID_NUM_INTERNAL * cols;
87       for (i = 0; i < pool->languagecacheother; i++, row += cols)
88         if (*row == keyname)
89           break;
90       if (i >= pool->languagecacheother)
91         {
92           pool->languagecache = sat_realloc2(pool->languagecache, pool->languagecacheother + 1, cols * sizeof(Id));
93           pool->languagecacheother++;
94           row = pool->languagecache + cols * (ID_NUM_INTERNAL + pool->languagecacheother++);
95         }
96     }
97   else
98     row = pool->languagecache + keyname * cols;
99   row++;        /* skip keyname */
100   for (i = 0; i < pool->nlanguages; i++, row++)
101     {
102       if (!*row)
103         {
104           char *p;
105           const char *kn;
106
107           kn = id2str(pool, keyname);
108           p = sat_malloc(strlen(kn) + strlen(pool->languages[i]) + 2);
109           sprintf(p, "%s:%s", kn, pool->languages[i]);
110           *row = str2id(pool, p, 1);
111           sat_free(p);
112         }
113       str = repo_lookup_str(s, *row);
114       if (str)
115         return str;
116     }
117   return repo_lookup_str(s, keyname);
118 }
119
120 unsigned int
121 solvable_lookup_num(Solvable *s, Id keyname, unsigned int notfound)
122 {
123   Repo *repo = s->repo;
124   Pool *pool;
125   Repodata *data;
126   int i, j, n;
127
128   if (!repo)
129     return 0;
130   pool = repo->pool;
131   if (keyname == RPM_RPMDBID)
132     {
133       if (repo->rpmdbid)
134         return repo->rpmdbid[(s - pool->solvables) - repo->start];
135       return notfound;
136     }
137   n = s - pool->solvables;
138   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
139     {
140       if (n < data->start || n >= data->end)
141         continue;
142       for (j = 1; j < data->nkeys; j++)
143         {
144           if (data->keys[j].name == keyname
145               && (data->keys[j].type == REPOKEY_TYPE_U32
146                   || data->keys[j].type == REPOKEY_TYPE_NUM
147                   || data->keys[j].type == REPOKEY_TYPE_CONSTANT))
148             {
149               unsigned int value;
150               if (repodata_lookup_num(data, n - data->start, j, &value))
151                 return value;
152             }
153         }
154     }
155   return notfound;
156 }
157
158 int
159 solvable_lookup_void(Solvable *s, Id keyname)
160 {
161   Repo *repo = s->repo;
162   Pool *pool;
163   Repodata *data;
164   int i, j, n;
165
166   if (!repo)
167     return 0;
168   pool = repo->pool;
169   n = s - pool->solvables;
170   for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++)
171     {
172       if (n < data->start || n >= data->end)
173         continue;
174       for (j = 1; j < data->nkeys; j++)
175         {
176           if (data->keys[j].name == keyname
177               && (data->keys[j].type == REPOKEY_TYPE_VOID))
178             {
179               if (repodata_lookup_void(data, n - data->start, j))
180                 return 1;
181             }
182         }
183     }
184   return 0;
185 }
186
187 char *
188 solvable_get_location(Solvable *s, unsigned int *medianrp)
189 {
190   Pool *pool;
191   int l = 0;
192   char *loc;
193   const char *mediadir, *mediafile;
194
195   *medianrp = 0;
196   if (!s->repo)
197     return 0;
198   pool = s->repo->pool;
199   *medianrp = solvable_lookup_num(s, SOLVABLE_MEDIANR, 1);
200   if (solvable_lookup_void(s, SOLVABLE_MEDIADIR))
201     mediadir = id2str(pool, s->arch);
202   else
203     mediadir = solvable_lookup_str(s, SOLVABLE_MEDIADIR);
204   if (mediadir)
205     l = strlen(mediadir) + 1;
206   if (solvable_lookup_void(s, SOLVABLE_MEDIAFILE))
207     {
208       const char *name, *evr, *arch;
209       name = id2str(pool, s->name);
210       evr = id2str(pool, s->evr);
211       arch = id2str(pool, s->arch);
212       /* name-evr.arch.rpm */
213       loc = sat_malloc(l + strlen(name) + strlen(evr) + strlen(arch) + 7);
214       if (mediadir)
215         sprintf(loc, "%s/%s-%s.%s.rpm", mediadir, name, evr, arch);
216       else
217         sprintf(loc, "%s-%s.%s.rpm", name, evr, arch);
218     }
219   else
220     {
221       mediafile = solvable_lookup_str(s, SOLVABLE_MEDIAFILE);
222       if (!mediafile)
223         return 0;
224       loc = sat_malloc(l + strlen(mediafile) + 1);
225       if (mediadir)
226         sprintf(loc, "%s/%s", mediadir, mediafile);
227       else
228         strcpy(loc, mediafile);
229     }
230   return loc;
231 }