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