rpm  5.4.10
rpmal.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmiotypes.h> /* XXX fnpyKey */
9 #include <rpmbf.h>
10 
11 #include <rpmtag.h>
12 #include <rpmtypes.h>
13 
14 #define _RPMDS_INTERNAL
15 #include <rpmds.h>
16 #include <rpmal.h>
17 
18 #include "debug.h"
19 
20 typedef /*@abstract@*/ struct availablePackage_s * availablePackage;
21 
22 /*@access alKey @*/
23 /*@access alNum @*/
24 /*@access rpmal @*/
25 /*@access rpmds @*/
26 /*@access availablePackage @*/
27 
28 /*@access fnpyKey @*/ /* XXX suggestedKeys array */
29 
30 /*@unchecked@*/
31 int _rpmal_debug = 0;
32 
37 /*@refcounted@*/ /*@null@*/
39 /*@refcounted@*/ /*@null@*/
40  rpmbf bf;
44 /*@exposed@*/ /*@dependent@*/ /*@null@*/
47 };
48 
49 typedef /*@abstract@*/ struct availableIndexEntry_s * availableIndexEntry;
50 /*@access availableIndexEntry@*/
51 
52 typedef enum {
55 
60 /*@exposed@*/ /*@dependent@*/ /*@null@*/
62 /*@observer@*/
63  const char * entry;
64  unsigned short entryLen;
65  unsigned short entryIx;
67 };
68 
69 typedef /*@abstract@*/ struct availableIndex_s * availableIndex;
70 /*@access availableIndex@*/
71 
76 /*@null@*/
77  availableIndexEntry index;
78  int size;
79  int k;
80 };
81 
85 struct rpmal_s {
86  struct rpmioItem_s _item;
87 /*@owned@*/ /*@null@*/
88  availablePackage list;
90  int delta;
91  int size;
92  int alloced;
94 };
95 
96 #ifdef __cplusplus
97 GENfree(availablePackage)
98 GENfree(availableIndexEntry)
99 GENfree(fnpyKey *)
100 #endif /* __cplusplus */
101 
102 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al,
103  /*@null@*/ alKey pkgKey)
104  /*@*/
105 {
106  /*@-nullret -temptrans -retalias @*/
107  union { alKey key; alNum num; } u;
108  u.num = 0;
109  u.key = pkgKey;
110  return u.num;
111  /*@=nullret =temptrans =retalias @*/
112 }
113 
114 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al,
115  /*@null@*/ alNum pkgNum)
116  /*@*/
117 {
118  /*@-nullret -temptrans -retalias @*/
119  union { alKey key; alNum num; } u;
120  u.key = 0;
121  u.num = pkgNum;
122  return u.key;
123  /*@=nullret =temptrans =retalias @*/
124 }
125 
130 static void rpmalFreeIndex(rpmal al)
131  /*@modifies al @*/
132 {
133  availableIndex ai = &al->index;
134  if (ai->size > 0) {
135  ai->index = _free(ai->index);
136  ai->size = 0;
137  }
138 }
139 
140 static void rpmalFini(void * _al)
141 {
142  rpmal al = (rpmal) _al;
143  availablePackage alp;
144  int i;
145 
146  if ((alp = al->list) != NULL)
147  for (i = 0; i < al->size; i++, alp++) {
148  (void)rpmdsFree(alp->provides);
149  alp->provides = NULL;
150  (void)rpmbfFree(alp->bf);
151  alp->bf = NULL;
152  }
153 
154  al->list = _free(al->list);
155  al->alloced = 0;
156  rpmalFreeIndex(al);
157 }
158 
159 /*@unchecked@*/ /*@only@*/ /*@null@*/
161 
162 static rpmal rpmalGetPool(/*@null@*/ rpmioPool pool)
163  /*@globals _rpmdsPool, fileSystem, internalState @*/
164  /*@modifies pool, _rpmdsPool, fileSystem, internalState @*/
165 {
166  rpmal al;
167 
168  if (_rpmalPool == NULL) {
169  _rpmalPool = rpmioNewPool("al", sizeof(*al), -1, _rpmal_debug,
170  NULL, NULL, rpmalFini);
171  pool = _rpmalPool;
172  }
173  al = (rpmal) rpmioGetPool(pool, sizeof(*al));
174  memset(((char *)al)+sizeof(al->_item), 0, sizeof(*al)-sizeof(al->_item));
175  return al;
176 }
177 
178 rpmal rpmalNew(int delta)
179 {
180  rpmal al = rpmalGetPool(_rpmalPool);
181  availableIndex ai = &al->index;
182 
183  al->delta = delta;
184  al->size = 0;
185  al->list = (availablePackage) xcalloc(al->delta, sizeof(*al->list));
186  al->alloced = al->delta;
187 
188  ai->index = NULL;
189  ai->size = 0;
190 
191  return rpmalLink(al, __FUNCTION__);
192 }
193 
194 void rpmalDel(rpmal al, alKey pkgKey)
195 {
196  alNum pkgNum = alKey2Num(al, pkgKey);
197  availablePackage alp;
198 
199  if (al == NULL || al->list == NULL)
200  return; /* XXX can't happen */
201 
202  alp = al->list + pkgNum;
203 
204  (void)rpmdsFree(alp->provides);
205  alp->provides = NULL;
206  (void)rpmbfFree(alp->bf);
207  alp->bf = NULL;
208 
209  memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */
210  return;
211 }
212 
213 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
215 {
216  alNum pkgNum;
217  rpmal al;
218  availablePackage alp;
219 
220  /* If list doesn't exist yet, create. */
221  if (*alistp == NULL)
222  *alistp = rpmalNew(5);
223  al = *alistp;
224  pkgNum = alKey2Num(al, pkgKey);
225 
226  if (pkgNum >= 0 && pkgNum < al->size) {
227  rpmalDel(al, pkgKey);
228  } else {
229  if (al->size == al->alloced) {
230  al->alloced += al->delta;
231  al->list = (availablePackage) xrealloc(al->list, sizeof(*al->list) * al->alloced);
232  }
233  pkgNum = al->size++;
234  }
235 
236  if (al->list == NULL)
237  return RPMAL_NOMATCH; /* XXX can't happen */
238 
239  alp = al->list + pkgNum;
240 
241  alp->key = key;
242  alp->tscolor = tscolor;
243 
244 /*@-assignexpose -castexpose @*/
245  alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
246  alp->bf = rpmbfLink(rpmfiFNBF(fi));
247 /*@=assignexpose =castexpose @*/
248 
249  rpmalFreeIndex(al);
250 
251 assert(((alNum)(alp - al->list)) == pkgNum);
252  return ((alKey)(alp - al->list));
253 }
254 
261 static int indexcmp(const void * one, const void * two)
262  /*@*/
263 {
264  /*@-castexpose@*/
265  const availableIndexEntry a = (const availableIndexEntry) one;
266  const availableIndexEntry b = (const availableIndexEntry) two;
267  /*@=castexpose@*/
268  int lenchk;
269 
270  lenchk = a->entryLen - b->entryLen;
271  if (lenchk)
272  return lenchk;
273 
274  return strcmp(a->entry, b->entry);
275 }
276 
278 {
279  rpmuint32_t dscolor;
280  const char * Name;
281  alNum pkgNum = alKey2Num(al, pkgKey);
282  availableIndex ai = &al->index;
283  availableIndexEntry aie;
284  int ix;
285 
286  if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
287  return;
288  if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
289  return;
290 
291  if (rpmdsInit(provides) != NULL)
292  while (rpmdsNext(provides) >= 0) {
293 
294  if ((Name = provides->N[provides->i]) == NULL)
295  continue; /* XXX can't happen */
296 
297  /* Ignore colored provides not in our rainbow. */
298  dscolor = rpmdsColor(provides);
299  if (tscolor && dscolor && !(tscolor & dscolor))
300  continue;
301 
302  aie = ai->index + ai->k;
303  ai->k++;
304 
305  aie->pkgKey = pkgKey;
306 /*@-assignexpose@*/
307  aie->entry = Name;
308 /*@=assignexpose@*/
309  aie->entryLen = (unsigned short)strlen(Name);
310  ix = rpmdsIx(provides);
311 
312 /* XXX make sure that element index fits in unsigned short */
313 assert(ix < 0x10000);
314 
315  aie->entryIx = ix;
316  aie->type = IET_PROVIDES;
317  }
318 }
319 
321 {
322  availableIndex ai;
323  availablePackage alp;
324  int i;
325 
326  if (al == NULL || al->list == NULL) return;
327  ai = &al->index;
328 
329  ai->size = 0;
330  for (i = 0; i < al->size; i++) {
331  alp = al->list + i;
332  if (alp->provides != NULL)
333  ai->size += rpmdsCount(alp->provides);
334  }
335  if (ai->size == 0) return;
336 
337  ai->index = (availableIndexEntry) xrealloc(ai->index, ai->size * sizeof(*ai->index));
338  ai->k = 0;
339  for (i = 0; i < al->size; i++) {
340  alp = al->list + i;
341  rpmalAddProvides(al, alNum2Key(NULL, (alNum)i), alp->provides, alp->tscolor);
342  }
343 
344  /* Reset size to the no. of provides added. */
345  ai->size = ai->k;
346  qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
347 }
348 
349 fnpyKey *
350 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
351 {
352  fnpyKey * ret = NULL;
353  int found = 0;
354  const char * fn;
355  size_t nfn;
356  int i;
357 
358  if (keyp) *keyp = RPMAL_NOMATCH;
359 
360  if (al == NULL || (fn = rpmdsN(ds)) == NULL || *fn != '/')
361  goto exit;
362  nfn = strlen(fn);
363 
364  if (al->list != NULL) /* XXX always true */
365  for (i = 0; i < al->size; i++) {
366  availablePackage alp = al->list + i;
367 
368  if (!rpmbfChk(alp->bf, fn, nfn))
369  continue;
370 
371  rpmdsNotify(ds, _("(added files)"), 0);
372 
373  ret = (fnpyKey *) xrealloc(ret, (found + 2) * sizeof(*ret));
374  if (ret) /* can't happen */
375  ret[found] = alp->key;
376  if (keyp)
377  *keyp = alNum2Key(al, i);
378  found++;
379  }
380 
381  if (ret)
382  ret[found] = NULL;
383 
384 exit:
385 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
386  return ret;
387 /*@=nullstate@*/
388 }
389 
390 fnpyKey *
391 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
392 {
393  availableIndex ai;
394  availableIndexEntry needle;
395  availableIndexEntry match;
396  fnpyKey * ret = NULL;
397  int found = 0;
398  const char * KName;
399  availablePackage alp;
400  int rc;
401 
402  if (keyp) *keyp = RPMAL_NOMATCH;
403 
404  if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
405  goto exit;
406 
407  if (*KName == '/') {
408  /* First, look for files "contained" in package ... */
409  ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
410  if (ret != NULL && *ret != NULL)
411  goto exit;
412  ret = _free(ret);
413  /* ... then, look for files "provided" by package. */
414  }
415 
416  ai = &al->index;
417  if (ai->index == NULL || ai->size <= 0)
418  goto exit;
419 
420  needle = (availableIndexEntry)
421  memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
422  /*@-assignexpose -temptrans@*/
423  needle->entry = KName;
424  /*@=assignexpose =temptrans@*/
425  needle->entryLen = (unsigned short)strlen(needle->entry);
426 
427  match = (availableIndexEntry)
428  bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
429  if (match == NULL)
430  goto exit;
431 
432  /* rewind to the first match */
433  while (match > ai->index && indexcmp(match-1, needle) == 0)
434  match--;
435 
436  if (al->list != NULL) /* XXX always true */
437  for (ret = NULL, found = 0;
438  match < ai->index + ai->size && indexcmp(match, needle) == 0;
439  match++)
440  {
441  alp = al->list + alKey2Num(al, match->pkgKey);
442 
443  rc = 0;
444  if (alp->provides != NULL) /* XXX can't happen */
445  switch (match->type) {
446  case IET_PROVIDES:
447  /* XXX single step on rpmdsNext to regenerate DNEVR string */
448  (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
449  if (rpmdsNext(alp->provides) >= 0)
450  rc = rpmdsCompare(alp->provides, ds);
451 
452  if (rc)
453  rpmdsNotify(ds, _("(added provide)"), 0);
454 
455  /*@switchbreak@*/ break;
456  }
457 
458  if (rc) {
459  ret = (fnpyKey *) xrealloc(ret, (found + 2) * sizeof(*ret));
460  if (ret) /* can't happen */
461  ret[found] = alp->key;
462 /*@-dependenttrans@*/
463  if (keyp)
464  *keyp = match->pkgKey;
465 /*@=dependenttrans@*/
466  found++;
467  }
468  }
469 
470  if (ret)
471  ret[found] = NULL;
472 
473 exit:
474 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
475  return ret;
476 /*@=nullstate@*/
477 }
478 
479 fnpyKey
480 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
481 {
482  fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
483 
484  if (tmp) {
485  fnpyKey ret = tmp[0];
486  free(tmp);
487  return ret;
488  }
489  return NULL;
490 }
rpmds rpmdsInit(rpmds ds)
Initialize dependency set iterator.
Definition: rpmds.c:943
rpmal rpmalLink(rpmal al, const char *msg)
Reference available list.
static void rpmalFreeIndex(rpmal al)
Destroy available item index.
Definition: rpmal.c:130
A single available item (e.g.
Definition: rpmal.c:59
int alNum
An added/available package retrieval index.
Definition: rpmal.h:23
rpmioPool _rpmalPool
Definition: rpmal.c:160
Index of all available items.
Definition: rpmal.c:75
alKey rpmalAdd(rpmal *alistp, alKey pkgKey, fnpyKey key, rpmds provides, rpmfi fi, rpmuint32_t tscolor)
Add package to available list.
Definition: rpmal.c:213
void * rpmfiFNBF(rpmfi fi)
Return FN Bloom filter from file info set.
Definition: rpmfi.c:181
rpmuint32_t tscolor
Definition: rpmal.c:93
static rpmal rpmalGetPool(rpmioPool pool)
Definition: rpmal.c:162
availablePackage list
Definition: rpmal.c:88
struct rpmds_s * rpmds
Dependency tag sets from a header, so that a header can be discarded early.
Definition: rpmtypes.h:28
rpmds rpmdsFree(rpmds ds)
Destroy a dependency set.
availableIndexEntry index
Definition: rpmal.c:77
char * alloca()
unsigned int rpmuint32_t
Definition: rpmiotypes.h:25
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:301
int alloced
Definition: rpmal.c:92
static void rpmalFini(void *_al)
Definition: rpmal.c:140
struct availableIndexEntry_s * availableIndexEntry
Definition: rpmal.c:49
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:221
rpmal rpmalNew(int delta)
Initialize available list.
Definition: rpmal.c:178
static alNum alKey2Num(const rpmal al, alKey pkgKey)
Definition: rpmal.c:102
struct rpmfi_s * rpmfi
File info tag sets from a header, so that a header can be discarded early.
Definition: rpmfi.h:78
int delta
Definition: rpmal.c:90
int rpmdsCompare(const rpmds A, const rpmds B)
Compare two versioned dependency ranges, looking for overlap.
Definition: rpmds.c:4347
int _rpmal_debug
Definition: rpmal.c:31
#define RPMAL_NOMATCH
Definition: rpmal.h:17
void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, rpmuint32_t tscolor)
Add package provides to available list index.
Definition: rpmal.c:277
void rpmdsNotify(rpmds ds, const char *where, int rc)
Notify of results of dependency match.
Definition: rpmds.c:899
Set of available packages, items, and directories.
Definition: rpmal.c:85
int rpmdsNext(rpmds ds)
Return next dependency set iterator index.
Definition: rpmds.c:912
Structure(s) used for dependency tag sets.
struct availableIndex_s index
Definition: rpmal.c:89
int rpmdsCount(const rpmds ds)
Return dependency set count.
Definition: rpmds.c:636
void * alKey
An added/available package retrieval key.
Definition: rpmtypes.h:19
fnpyKey * rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey *keyp)
Check added package file lists for package(s) that provide a file.
Definition: rpmal.c:350
fnpyKey key
Definition: rpmal.c:45
const char * rpmdsN(const rpmds ds)
Return current dependency name.
Definition: rpmds.c:668
struct availableIndex_s * availableIndex
Definition: rpmal.c:69
unsigned short entryLen
Definition: rpmal.c:64
struct availablePackage_s * availablePackage
Definition: rpmal.c:20
fnpyKey rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey *keyp)
Check added package file lists for first package that has a provide.
Definition: rpmal.c:480
rpmds rpmdsLink(rpmds ds, const char *msg)
Reference a dependency set instance.
indexEntryType_e type
Definition: rpmal.c:66
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:110
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
const void * fnpyKey
Definition: rpmiotypes.h:118
static int indexcmp(const void *one, const void *two)
Compare two available index entries by name (qsort/bsearch).
Definition: rpmal.c:261
unsigned short entryIx
Definition: rpmal.c:65
Info about a single package to be installed.
Definition: rpmal.c:36
void rpmalDel(rpmal al, alKey pkgKey)
Delete package from available list.
Definition: rpmal.c:194
int rpmdsIx(const rpmds ds)
Return dependency set index.
Definition: rpmds.c:641
void rpmalMakeIndex(rpmal al)
Generate index for available list.
Definition: rpmal.c:320
rpmuint32_t rpmdsColor(const rpmds ds)
Return current dependency color.
Definition: rpmds.c:789
fnpyKey * rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey *keyp)
Check added package file lists for package(s) that have a provide.
Definition: rpmal.c:391
struct rpmioItem_s _item
Definition: rpmal.c:86
Structures used for managing added/available package lists.
indexEntryType_e
Definition: rpmal.c:52
#define _(Text)
Definition: system.h:30
int size
Definition: rpmal.c:91
rpmds provides
Definition: rpmal.c:38
static alKey alNum2Key(const rpmal al, alNum pkgNum)
Definition: rpmal.c:114
int rpmdsSetIx(rpmds ds, int ix)
Set dependency set index.
Definition: rpmds.c:646
rpmuint32_t tscolor
Definition: rpmal.c:42
struct rpmal_s * rpmal
Definition: rpmal.h:28
#define xrealloc
Definition: system.h:36
const char * entry
Definition: rpmal.c:63