rpm  4.5
rpmal.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmlib.h>
8 
9 #include "rpmal.h"
10 #define _RPMDS_INTERNAL
11 #include "rpmds.h"
12 #include "rpmfi.h"
13 
14 #include "debug.h"
15 
16 typedef /*@abstract@*/ struct availablePackage_s * availablePackage;
17 
18 /*@unchecked@*/
19 int _rpmal_debug = 0;
20 
21 /*@access alKey @*/
22 /*@access alNum @*/
23 /*@access rpmal @*/
24 /*@access rpmds @*/
25 /*@access availablePackage @*/
26 
27 /*@access fnpyKey @*/ /* XXX suggestedKeys array */
28 
33 /*@refcounted@*/ /*@null@*/
35 /*@refcounted@*/ /*@null@*/
40 /*@exposed@*/ /*@dependent@*/ /*@null@*/
43 };
44 
45 typedef /*@abstract@*/ struct availableIndexEntry_s * availableIndexEntry;
46 /*@access availableIndexEntry@*/
47 
52 /*@exposed@*/ /*@dependent@*/ /*@null@*/
54 /*@observer@*/
55  const char * entry;
56  unsigned short entryLen;
57  unsigned short entryIx;
60  } type;
61 };
62 
63 typedef /*@abstract@*/ struct availableIndex_s * availableIndex;
64 /*@access availableIndex@*/
65 
70 /*@null@*/
71  availableIndexEntry index;
72  int size;
73  int k;
74 };
75 
76 typedef /*@abstract@*/ struct fileIndexEntry_s * fileIndexEntry;
77 /*@access fileIndexEntry@*/
78 
83 /*@dependent@*/ /*@relnull@*/
84  const char * baseName;
88 };
89 
90 typedef /*@abstract@*/ struct dirInfo_s * dirInfo;
91 /*@access dirInfo@*/
92 
96 struct dirInfo_s {
97 /*@owned@*/ /*@relnull@*/
98  const char * dirName;
99  int dirNameLen;
100 /*@owned@*/
101  fileIndexEntry files;
102  int numFiles;
103 };
104 
108 struct rpmal_s {
109 /*@owned@*/ /*@null@*/
110  availablePackage list;
112  int delta;
113  int size;
114  int alloced;
116  int numDirs;
117 /*@owned@*/ /*@null@*/
118  dirInfo dirs;
119 };
120 
125 static void rpmalFreeIndex(rpmal al)
126  /*@modifies al @*/
127 {
128  availableIndex ai = &al->index;
129  if (ai->size > 0) {
130  ai->index = _free(ai->index);
131  ai->size = 0;
132  }
133 }
134 
135 #ifdef DYING
136 
141 static int alGetSize(/*@null@*/ const rpmal al)
142  /*@*/
143 {
144  return (al != NULL ? al->size : 0);
145 }
146 #endif
147 
148 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al,
149  /*@null@*/ alKey pkgKey)
150  /*@*/
151 {
152  /*@-nullret -temptrans -retalias @*/
153  return ((alNum)pkgKey);
154  /*@=nullret =temptrans =retalias @*/
155 }
156 
157 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al,
158  /*@null@*/ alNum pkgNum)
159  /*@*/
160 {
161  /*@-nullret -temptrans -retalias @*/
162  return ((alKey)pkgNum);
163  /*@=nullret =temptrans =retalias @*/
164 }
165 
166 #ifdef DYING
167 
173 /*@dependent@*/ /*@null@*/
174 static availablePackage alGetPkg(/*@null@*/ const rpmal al,
175  /*@null@*/ alKey pkgKey)
176  /*@*/
177 {
178  alNum pkgNum = alKey2Num(al, pkgKey);
179  availablePackage alp = NULL;
180 
181  if (al != NULL && pkgNum >= 0 && pkgNum < alGetSize(al)) {
182  if (al->list != NULL)
183  alp = al->list + pkgNum;
184  }
185  return alp;
186 }
187 #endif
188 
189 rpmal rpmalCreate(int delta)
190 {
191  rpmal al = xcalloc(1, sizeof(*al));
192  availableIndex ai = &al->index;
193 
194  al->delta = delta;
195  al->size = 0;
196  al->list = xcalloc(al->delta, sizeof(*al->list));
197  al->alloced = al->delta;
198 
199  ai->index = NULL;
200  ai->size = 0;
201 
202  al->numDirs = 0;
203  al->dirs = NULL;
204  return al;
205 }
206 
208 {
209  availablePackage alp;
210  dirInfo die;
211  int i;
212 
213  if (al == NULL)
214  return NULL;
215 
216  if ((alp = al->list) != NULL)
217  for (i = 0; i < al->size; i++, alp++) {
218  alp->provides = rpmdsFree(alp->provides);
219  alp->fi = rpmfiFree(alp->fi);
220  }
221 
222  if ((die = al->dirs) != NULL)
223  for (i = 0; i < al->numDirs; i++, die++) {
224  die->dirName = _free(die->dirName);
225  die->files = _free(die->files);
226  }
227  al->dirs = _free(al->dirs);
228  al->numDirs = 0;
229 
230  al->list = _free(al->list);
231  al->alloced = 0;
232  rpmalFreeIndex(al);
233  al = _free(al);
234  return NULL;
235 }
236 
243 static int dieCompare(const void * one, const void * two)
244  /*@*/
245 {
246  /*@-castexpose@*/
247  const dirInfo a = (const dirInfo) one;
248  const dirInfo b = (const dirInfo) two;
249  /*@=castexpose@*/
250  int lenchk = a->dirNameLen - b->dirNameLen;
251 
252  if (lenchk || a->dirNameLen == 0)
253  return lenchk;
254 
255  if (a->dirName == NULL || b->dirName == NULL)
256  return lenchk;
257 
258  /* XXX FIXME: this might do "backward" strcmp for speed */
259  return strcmp(a->dirName, b->dirName);
260 }
261 
268 static int fieCompare(const void * one, const void * two)
269  /*@*/
270 {
271  /*@-castexpose@*/
272  const fileIndexEntry a = (const fileIndexEntry) one;
273  const fileIndexEntry b = (const fileIndexEntry) two;
274  /*@=castexpose@*/
275  int lenchk = a->baseNameLen - b->baseNameLen;
276 
277  if (lenchk)
278  return lenchk;
279 
280  if (a->baseName == NULL || b->baseName == NULL)
281  return lenchk;
282 
283 #ifdef NOISY
284 /*@-modfilesys@*/
285 if (_rpmal_debug) {
286 fprintf(stderr, "\t\tstrcmp(%p:%p, %p:%p)", a, a->baseName, b, b->baseName);
287 #if 0
288 fprintf(stderr, " a %s", a->baseName);
289 #endif
290 fprintf(stderr, " b %s", a->baseName);
291 fprintf(stderr, "\n");
292 }
293 /*@=modfilesys@*/
294 #endif
295 
296  return strcmp(a->baseName, b->baseName);
297 }
298 
299 void rpmalDel(rpmal al, alKey pkgKey)
300 {
301  alNum pkgNum = alKey2Num(al, pkgKey);
302  availablePackage alp;
303  rpmfi fi;
304 
305  if (al == NULL || al->list == NULL)
306  return; /* XXX can't happen */
307 
308  alp = al->list + pkgNum;
309 
310 /*@-modfilesys@*/
311 if (_rpmal_debug)
312 fprintf(stderr, "*** del %p[%d]\n", al->list, pkgNum);
313 /*@=modfilesys@*/
314 
315  /* Delete directory/file info entries from added package list. */
316  if ((fi = alp->fi) != NULL)
317  if (rpmfiFC(fi) > 0) {
318  int origNumDirs = al->numDirs;
319  int dx;
320  dirInfo dieNeedle =
321  memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
322  dirInfo die;
323  int last;
324  int i;
325 
326  /* XXX FIXME: We ought to relocate the directory list here */
327 
328  if (al->dirs != NULL)
329  for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
330  {
331  fileIndexEntry fie;
332 
333  (void) rpmfiSetDX(fi, dx);
334 
335  /*@-assignexpose -dependenttrans -observertrans@*/
336  dieNeedle->dirName = (char *) rpmfiDN(fi);
337  /*@=assignexpose =dependenttrans =observertrans@*/
338  dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
339  ? strlen(dieNeedle->dirName) : 0);
340 /*@-boundswrite@*/
341  die = bsearch(dieNeedle, al->dirs, al->numDirs,
342  sizeof(*dieNeedle), dieCompare);
343 /*@=boundswrite@*/
344  if (die == NULL)
345  continue;
346 
347 /*@-modfilesys@*/
348 if (_rpmal_debug)
349 fprintf(stderr, "--- die[%5d] %p [%3d] %s\n", (int)(die - al->dirs), die, die->dirNameLen, die->dirName);
350 /*@=modfilesys@*/
351 
352  last = die->numFiles;
353  fie = die->files + last - 1;
354  for (i = last - 1; i >= 0; i--, fie--) {
355  if (fie->pkgNum != pkgNum)
356  /*@innercontinue@*/ continue;
357  die->numFiles--;
358 
359  if (i < die->numFiles) {
360 /*@-modfilesys@*/
361 if (_rpmal_debug)
362 fprintf(stderr, "\t%p[%3d] memmove(%p:%p,%p:%p,0x%x) %s <- %s\n", die->files, die->numFiles, fie, fie->baseName, fie+1, (fie+1)->baseName, (unsigned) ((die->numFiles - i) * sizeof(*fie)), fie->baseName, (fie+1)->baseName);
363 /*@=modfilesys@*/
364 
365 /*@-bounds@*/
366  memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
367 /*@=bounds@*/
368  }
369 /*@-modfilesys@*/
370 if (_rpmal_debug)
371 fprintf(stderr, "\t%p[%3d] memset(%p,0,0x%x) %p [%3d] %s\n", die->files, die->numFiles, die->files + die->numFiles, (unsigned)sizeof(*fie), fie->baseName, fie->baseNameLen, fie->baseName);
372 /*@=modfilesys@*/
373  memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */
374 
375  }
376  if (die->numFiles > 0) {
377  if (last > i)
378  die->files = xrealloc(die->files,
379  die->numFiles * sizeof(*die->files));
380  continue;
381  }
382  die->files = _free(die->files);
383  die->dirName = _free(die->dirName);
384  al->numDirs--;
385  if ((die - al->dirs) < al->numDirs) {
386 /*@-modfilesys@*/
387 if (_rpmal_debug)
388 fprintf(stderr, " die[%5d] memmove(%p,%p,0x%x)\n", (int)(die - al->dirs), die, die+1, (unsigned)((al->numDirs - (die - al->dirs)) * sizeof(*die)));
389 /*@=modfilesys@*/
390 
391 /*@-bounds@*/
392  memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
393 /*@=bounds@*/
394  }
395 
396 /*@-modfilesys@*/
397 if (_rpmal_debug)
398 fprintf(stderr, " die[%5d] memset(%p,0,0x%x)\n", al->numDirs, al->dirs + al->numDirs, (unsigned)sizeof(*die));
399 /*@=modfilesys@*/
400  memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */
401  }
402 
403  if (origNumDirs > al->numDirs) {
404  if (al->numDirs > 0)
405  al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
406  else
407  al->dirs = _free(al->dirs);
408  }
409  }
410 
411  alp->provides = rpmdsFree(alp->provides);
412  alp->fi = rpmfiFree(alp->fi);
413 
414 /*@-boundswrite@*/
415  memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */
416 /*@=boundswrite@*/
417  return;
418 }
419 
420 /*@-bounds@*/
421 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key,
422  rpmds provides, rpmfi fi, uint_32 tscolor)
423 {
424  alNum pkgNum;
425  rpmal al;
426  availablePackage alp;
427 
428  /* If list doesn't exist yet, create. */
429  if (*alistp == NULL)
430  *alistp = rpmalCreate(5);
431  al = *alistp;
432  pkgNum = alKey2Num(al, pkgKey);
433 
434  if (pkgNum >= 0 && pkgNum < al->size) {
435  rpmalDel(al, pkgKey);
436  } else {
437  if (al->size == al->alloced) {
438  al->alloced += al->delta;
439  al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced);
440  }
441  pkgNum = al->size++;
442  }
443 
444  if (al->list == NULL)
445  return RPMAL_NOMATCH; /* XXX can't happen */
446 
447  alp = al->list + pkgNum;
448 
449  alp->key = key;
450  alp->tscolor = tscolor;
451 
452 /*@-modfilesys@*/
453 if (_rpmal_debug)
454 fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, pkgNum, tscolor);
455 /*@=modfilesys@*/
456 
457  alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)");
458  alp->fi = rpmfiLink(fi, "Files (rpmalAdd)");
459 
460  fi = rpmfiLink(alp->fi, "Files index (rpmalAdd)");
461  fi = rpmfiInit(fi, 0);
462  if (rpmfiFC(fi) > 0) {
463  dirInfo dieNeedle =
464  memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
465  dirInfo die;
466  int dc = rpmfiDC(fi);
467  int dx;
468  int * dirMapping = alloca(sizeof(*dirMapping) * dc);
469  int * dirUnique = alloca(sizeof(*dirUnique) * dc);
470  const char * DN;
471  int origNumDirs;
472  int first;
473 
474  /* XXX FIXME: We ought to relocate the directory list here */
475 
476  /* XXX enough space for all directories, late realloc to truncate. */
477  al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
478 
479  /* Only previously allocated dirInfo is sorted and bsearch'able. */
480  origNumDirs = al->numDirs;
481 
482  /* Package dirnames are not currently unique. Create unique mapping. */
483  for (dx = 0; dx < dc; dx++) {
484  int i = 0;
485  (void) rpmfiSetDX(fi, dx);
486  DN = rpmfiDN(fi);
487  if (DN != NULL)
488  for (i = 0; i < dx; i++) {
489  const char * iDN;
490  (void) rpmfiSetDX(fi, i);
491  iDN = rpmfiDN(fi);
492  if (iDN != NULL && !strcmp(DN, iDN))
493  /*@innerbreak@*/ break;
494  }
495  dirUnique[dx] = i;
496  }
497 
498  /* Map package dirs into transaction dirInfo index. */
499  for (dx = 0; dx < dc; dx++) {
500 
501  /* Non-unique package dirs use the 1st entry mapping. */
502  if (dirUnique[dx] < dx) {
503  dirMapping[dx] = dirMapping[dirUnique[dx]];
504  continue;
505  }
506 
507  /* Find global dirInfo mapping for first encounter. */
508  (void) rpmfiSetDX(fi, dx);
509 
510  /*@-assignexpose -dependenttrans -observertrans@*/
511  { DN = rpmfiDN(fi);
512 
513 #if defined(__ia64__)
514 /* XXX Make sure that autorelocated file dependencies are satisfied. */
515 #define DNPREFIX "/emul/ia32-linux"
516  if (!strncmp(DN, DNPREFIX, sizeof(DNPREFIX)-1))
517  DN += sizeof(DNPREFIX)-1;
518 #endif
519  dieNeedle->dirName = DN;
520  }
521  /*@=assignexpose =dependenttrans =observertrans@*/
522 
523  dieNeedle->dirNameLen = (dieNeedle->dirName != NULL
524  ? strlen(dieNeedle->dirName) : 0);
525  die = bsearch(dieNeedle, al->dirs, origNumDirs,
526  sizeof(*dieNeedle), dieCompare);
527  if (die) {
528  dirMapping[dx] = die - al->dirs;
529  } else {
530  dirMapping[dx] = al->numDirs;
531  die = al->dirs + al->numDirs;
532  if (dieNeedle->dirName != NULL)
533  die->dirName = xstrdup(dieNeedle->dirName);
534  die->dirNameLen = dieNeedle->dirNameLen;
535  die->files = NULL;
536  die->numFiles = 0;
537 /*@-modfilesys@*/
538 if (_rpmal_debug)
539 fprintf(stderr, "+++ die[%5d] %p [%3d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName);
540 /*@=modfilesys@*/
541 
542  al->numDirs++;
543  }
544  }
545 
546  for (first = rpmfiNext(fi); first >= 0;) {
547  fileIndexEntry fie;
548  int next;
549 
550  /* Find the first file of the next directory. */
551  dx = rpmfiDX(fi);
552  while ((next = rpmfiNext(fi)) >= 0) {
553  if (dx != rpmfiDX(fi))
554  /*@innerbreak@*/ break;
555  }
556  if (next < 0) next = rpmfiFC(fi); /* XXX reset end-of-list */
557 
558  die = al->dirs + dirMapping[dx];
559  die->files = xrealloc(die->files,
560  (die->numFiles + next - first) * sizeof(*die->files));
561 
562  fie = die->files + die->numFiles;
563 
564 /*@-modfilesys@*/
565 if (_rpmal_debug)
566 fprintf(stderr, " die[%5d] %p->files [%p[%d],%p) -> [%p[%d],%p)\n", dirMapping[dx], die,
567 die->files, die->numFiles, die->files+die->numFiles,
568 fie, (next - first), fie + (next - first));
569 /*@=modfilesys@*/
570 
571  /* Rewind to first file, generate file index entry for each file. */
572  fi = rpmfiInit(fi, first);
573  while ((first = rpmfiNext(fi)) >= 0 && first < next) {
574  /*@-assignexpose -dependenttrans -observertrans @*/
575  fie->baseName = rpmfiBN(fi);
576  /*@=assignexpose =dependenttrans =observertrans @*/
577  fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
578  fie->pkgNum = pkgNum;
579  fie->ficolor = rpmfiFColor(fi);
580 /*@-modfilesys@*/
581 if (_rpmal_debug)
582 fprintf(stderr, "\t%p[%3d] %p:%p[%2d] %s\n", die->files, die->numFiles, fie, fie->baseName, fie->baseNameLen, rpmfiFN(fi));
583 /*@=modfilesys@*/
584 
585  die->numFiles++;
586  fie++;
587  }
588  qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
589  }
590 
591  /* Resize the directory list. If any directories were added, resort. */
592  al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
593  if (origNumDirs != al->numDirs)
594  qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
595  }
596  fi = rpmfiUnlink(fi, "Files index (rpmalAdd)");
597 
598  rpmalFreeIndex(al);
599 
600 assert(((alNum)(alp - al->list)) == pkgNum);
601  return ((alKey)(alp - al->list));
602 }
603 /*@=bounds@*/
604 
611 static int indexcmp(const void * one, const void * two)
612  /*@*/
613 {
614  /*@-castexpose@*/
615  const availableIndexEntry a = (const availableIndexEntry) one;
616  const availableIndexEntry b = (const availableIndexEntry) two;
617  /*@=castexpose@*/
618  int lenchk;
619 
620  lenchk = a->entryLen - b->entryLen;
621  if (lenchk)
622  return lenchk;
623 
624  return strcmp(a->entry, b->entry);
625 }
626 
627 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, uint_32 tscolor)
628 {
629  uint_32 dscolor;
630  const char * Name;
631  alNum pkgNum = alKey2Num(al, pkgKey);
632  availableIndex ai = &al->index;
633  availableIndexEntry aie;
634  int ix;
635 
636  if (provides == NULL || pkgNum < 0 || pkgNum >= al->size)
637  return;
638  if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
639  return;
640 
641  if (rpmdsInit(provides) != NULL)
642  while (rpmdsNext(provides) >= 0) {
643 
644  if ((Name = provides->N[provides->i]) == NULL)
645  continue; /* XXX can't happen */
646 
647  /* Ignore colored provides not in our rainbow. */
648  dscolor = rpmdsColor(provides);
649  if (tscolor && dscolor && !(tscolor & dscolor))
650  continue;
651 
652  aie = ai->index + ai->k;
653  ai->k++;
654 
655  aie->pkgKey = pkgKey;
656 /*@-assignexpose@*/
657  aie->entry = Name;
658 /*@=assignexpose@*/
659  aie->entryLen = strlen(Name);
660  ix = rpmdsIx(provides);
661 
662 /* XXX make sure that element index fits in unsigned short */
663 assert(ix < 0x10000);
664 
665  aie->entryIx = ix;
666  aie->type = IET_PROVIDES;
667  }
668 }
669 
671 {
672  availableIndex ai;
673  availablePackage alp;
674  int i;
675 
676  if (al == NULL || al->list == NULL) return;
677  ai = &al->index;
678 
679  ai->size = 0;
680  for (i = 0; i < al->size; i++) {
681  alp = al->list + i;
682  if (alp->provides != NULL)
683  ai->size += rpmdsCount(alp->provides);
684  }
685  if (ai->size == 0) return;
686 
687  ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
688  ai->k = 0;
689  for (i = 0; i < al->size; i++) {
690  alp = al->list + i;
691  rpmalAddProvides(al, (alKey)i, alp->provides, alp->tscolor);
692  }
693 
694  /* Reset size to the no. of provides added. */
695  ai->size = ai->k;
696  qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
697 }
698 
699 fnpyKey *
700 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
701 {
702  uint_32 tscolor;
703  uint_32 ficolor;
704  int found = 0;
705  const char * dirName;
706  const char * baseName;
707  dirInfo dieNeedle =
708  memset(alloca(sizeof(*dieNeedle)), 0, sizeof(*dieNeedle));
709  dirInfo die;
710  fileIndexEntry fieNeedle =
711  memset(alloca(sizeof(*fieNeedle)), 0, sizeof(*fieNeedle));
712  fileIndexEntry fie;
713  availablePackage alp;
714  fnpyKey * ret = NULL;
715  const char * fileName;
716 
717  if (keyp) *keyp = RPMAL_NOMATCH;
718 
719  if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
720  return NULL;
721 
722  /* Solaris 2.6 bsearch sucks down on this. */
723  if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
724  return NULL;
725 
726  { char * t;
727  dirName = t = xstrdup(fileName);
728  if ((t = strrchr(t, '/')) != NULL) {
729  t++; /* leave the trailing '/' */
730  *t = '\0';
731  }
732  }
733 
734  dieNeedle->dirName = (char *) dirName;
735  dieNeedle->dirNameLen = strlen(dirName);
736  die = bsearch(dieNeedle, al->dirs, al->numDirs,
737  sizeof(*dieNeedle), dieCompare);
738  if (die == NULL)
739  goto exit;
740 
741  /* rewind to the first match */
742  while (die > al->dirs && dieCompare(die-1, dieNeedle) == 0)
743  die--;
744 
745  if ((baseName = strrchr(fileName, '/')) == NULL)
746  goto exit;
747  baseName++;
748 
749  /*@-branchstate@*/ /* FIX: ret is a problem */
750  for (found = 0, ret = NULL;
751  die < al->dirs + al->numDirs && dieCompare(die, dieNeedle) == 0;
752  die++)
753  {
754 
755 /*@-modfilesys@*/
756 if (_rpmal_debug)
757 fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
758 /*@=modfilesys@*/
759 
760 /*@-observertrans@*/
761  fieNeedle->baseName = baseName;
762 /*@=observertrans@*/
763  fieNeedle->baseNameLen = strlen(fieNeedle->baseName);
764  fie = bsearch(fieNeedle, die->files, die->numFiles,
765  sizeof(*fieNeedle), fieCompare);
766  if (fie == NULL)
767  continue; /* XXX shouldn't happen */
768 
769 /*@-modfilesys@*/
770 if (_rpmal_debug)
771 fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
772 /*@=modfilesys@*/
773 
774  alp = al->list + fie->pkgNum;
775 
776  /* Ignore colored files not in our rainbow. */
777  tscolor = alp->tscolor;
778  ficolor = fie->ficolor;
779  if (tscolor && ficolor && !(tscolor & ficolor))
780  continue;
781 
782  rpmdsNotify(ds, _("(added files)"), 0);
783 
784  ret = xrealloc(ret, (found+2) * sizeof(*ret));
785  if (ret) /* can't happen */
786  ret[found] = alp->key;
787  if (keyp)
788  *keyp = alNum2Key(al, fie->pkgNum);
789  found++;
790  }
791  /*@=branchstate@*/
792 
793 exit:
794  dirName = _free(dirName);
795  if (ret)
796  ret[found] = NULL;
797  return ret;
798 }
799 
800 fnpyKey *
801 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
802 {
803  availableIndex ai;
804  availableIndexEntry needle;
805  availableIndexEntry match;
806  fnpyKey * ret = NULL;
807  int found = 0;
808  const char * KName;
809  availablePackage alp;
810  int rc;
811 
812  if (keyp) *keyp = RPMAL_NOMATCH;
813 
814  if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
815  return ret;
816 
817  if (*KName == '/') {
818  /* First, look for files "contained" in package ... */
819  ret = rpmalAllFileSatisfiesDepend(al, ds, keyp);
820  if (ret != NULL && *ret != NULL)
821  return ret;
822  ret = _free(ret);
823  /* ... then, look for files "provided" by package. */
824  }
825 
826  ai = &al->index;
827  if (ai->index == NULL || ai->size <= 0)
828  return NULL;
829 
830  needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle));
831  /*@-assignexpose -temptrans@*/
832  needle->entry = KName;
833  /*@=assignexpose =temptrans@*/
834  needle->entryLen = strlen(needle->entry);
835 
836  match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
837  if (match == NULL)
838  return NULL;
839 
840  /* rewind to the first match */
841  while (match > ai->index && indexcmp(match-1, needle) == 0)
842  match--;
843 
844  if (al->list != NULL) /* XXX always true */
845  for (ret = NULL, found = 0;
846  match < ai->index + ai->size && indexcmp(match, needle) == 0;
847  match++)
848  {
849  alp = al->list + alKey2Num(al, match->pkgKey);
850 
851  rc = 0;
852  if (alp->provides != NULL) /* XXX can't happen */
853  switch (match->type) {
854  case IET_PROVIDES:
855  /* XXX single step on rpmdsNext to regenerate DNEVR string */
856  (void) rpmdsSetIx(alp->provides, match->entryIx - 1);
857  if (rpmdsNext(alp->provides) >= 0)
858  rc = rpmdsCompare(alp->provides, ds);
859 
860  if (rc)
861  rpmdsNotify(ds, _("(added provide)"), 0);
862 
863  /*@switchbreak@*/ break;
864  }
865 
866  /*@-branchstate@*/
867  if (rc) {
868  ret = xrealloc(ret, (found + 2) * sizeof(*ret));
869  if (ret) /* can't happen */
870  ret[found] = alp->key;
871 /*@-dependenttrans@*/
872  if (keyp)
873  *keyp = match->pkgKey;
874 /*@=dependenttrans@*/
875  found++;
876  }
877  /*@=branchstate@*/
878  }
879 
880  if (ret)
881  ret[found] = NULL;
882 
883 /*@-nullstate@*/ /* FIX: *keyp may be NULL */
884  return ret;
885 /*@=nullstate@*/
886 }
887 
888 fnpyKey
889 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp)
890 {
891  fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp);
892 
893  if (tmp) {
894  fnpyKey ret = tmp[0];
895  free(tmp);
896  return ret;
897  }
898  return NULL;
899 }