rpm  5.4.10
depends.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 <rpmcb.h>
10 #include <rpmbf.h>
11 #include <rpmmacro.h> /* XXX rpmExpand("%{_dependency_whiteout}" */
12 #include <envvar.h>
13 #include <ugid.h> /* XXX user()/group() probes */
14 
15 #include <rpmtag.h>
16 #define _RPMDB_INTERNAL /* XXX response cache needs dbiOpen et al. */
17 #include <rpmdb.h>
18 
19 #define _RPMEVR_INTERNAL
20 #include <rpmds.h>
21 #include <rpmfi.h>
22 
23 #define _RPMTE_INTERNAL
24 #include <rpmte.h>
25 #define _RPMTS_INTERNAL
26 #include <rpmcli.h> /* XXX rpmcliPackagesTotal */
27 
28 #include "debug.h"
29 
30 /*@access tsortInfo @*/
31 /*@access rpmte @*/ /* XXX for install <-> erase associate. */
32 /*@access rpmts @*/
33 /*@access rpmDiskSpaceInfo @*/
34 
35 #define CACHE_DEPENDENCY_RESULT 1
36 #if defined(CACHE_DEPENDENCY_RESULT)
37 /*@unchecked@*/
39 #endif
40 
41 /*@observer@*/ /*@unchecked@*/
42 const char *rpmNAME = PACKAGE;
43 
44 /*@observer@*/ /*@unchecked@*/
45 const char *rpmEVR = VERSION;
46 
47 /*@unchecked@*/
49 
56 static int uintcmp(const void * a, const void * b)
57  /*@requires maxRead(a) == 0 /\ maxRead(b) == 0 @*/
58 {
59  const uint32_t * aptr = (const uint32_t *) a;
60  const uint32_t * bptr = (const uint32_t *) b;
61  int rc = (*aptr - *bptr);
62  return rc;
63 }
64 
74 static int removePackage(rpmts ts, Header h, uint32_t hdrNum,
75  /*@null@*/ int * indexp,
76  /*@exposed@*/ /*@dependent@*/ /*@null@*/ alKey depends)
77  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
78  /*@modifies ts, h, *indexp, rpmGlobalMacroContext, fileSystem, internalState @*/
79 {
80  rpmte p;
81  int xx;
82 
83  /* Filter out duplicate erasures. */
84  if (ts->numRemovedPackages > 0 && ts->removedPackages != NULL) {
85  uint32_t * needle = NULL;
86  needle = (uint32_t *) bsearch(&hdrNum,
87  ts->removedPackages, ts->numRemovedPackages,
88  sizeof(*ts->removedPackages), uintcmp);
89  if (needle != NULL) {
90  /* XXX lastx should be per-call, not per-ts. */
91  if (indexp != NULL)
92  *indexp = needle - ts->removedPackages;
93  return 0;
94  }
95  }
96 
97  if (ts->rbf == NULL) {
98  static size_t n = 10000; /* XXX population estimate */
99  static double e = 1.0e-4;
100  size_t m = 0;
101  size_t k = 0;
102  rpmbfParams(n, e, &m, &k);
103  ts->rbf = rpmbfNew(m, k, 0);
104  }
105 
106  if (ts->numRemovedPackages == ts->allocedRemovedPackages) {
107  ts->allocedRemovedPackages += ts->delta;
108  ts->removedPackages = (uint32_t *) xrealloc(ts->removedPackages,
109  sizeof(ts->removedPackages) * ts->allocedRemovedPackages);
110  }
111 
112 assert(ts->removedPackages != NULL); /* XXX can't happen. */
113  xx = rpmbfAdd(ts->rbf, &hdrNum, sizeof(hdrNum));
114 assert(xx == 0);
115  ts->removedPackages[ts->numRemovedPackages] = hdrNum;
116  ts->numRemovedPackages++;
117  if (ts->numRemovedPackages > 1)
118  qsort(ts->removedPackages, ts->numRemovedPackages,
119  sizeof(*ts->removedPackages), uintcmp);
120 
121  if (ts->orderCount >= ts->orderAlloced) {
122  ts->orderAlloced += (ts->orderCount - ts->orderAlloced) + ts->delta;
123 /*@-type +voidabstract @*/
124  ts->order = (rpmte *) xrealloc(ts->order, sizeof(*ts->order) * ts->orderAlloced);
125 /*@=type =voidabstract @*/
126  }
127 
128  p = rpmteNew(ts, h, TR_REMOVED, NULL, NULL, hdrNum, depends);
129  ts->order[ts->orderCount] = p;
130  ts->numErasedFiles += rpmfiFC(rpmteFI(p, RPMTAG_BASENAMES));
131  if (indexp != NULL)
132  *indexp = ts->orderCount;
133  ts->orderCount++;
134 
135 /*@-nullstate@*/ /* XXX FIX: ts->order[] can be NULL. */
136  return 0;
137 /*@=nullstate@*/
138 }
139 
146 static int rpmHeadersIdentical(Header first, Header second)
147  /*@globals internalState @*/
148  /*@modifies internalState @*/
149 {
150  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
151  const char * one, * two;
152  int rc = 0;
153  int xx;
154 
155  he->tag = RPMTAG_HDRID;
156  xx = headerGet(first, he, 0);
157  one = he->p.str;
158  he->tag = RPMTAG_HDRID;
159  xx = headerGet(second, he, 0);
160  two = he->p.str;
161 
162  if (one && two)
163  rc = ((strcmp(one, two) == 0) ? 1 : 0);
164  else if (one && !two)
165  rc = 0;
166  else if (!one && two)
167  rc = 0;
168  else {
169  /* XXX Headers w/o digests case devolves to NEVR comparison. */
172  rc = rpmdsCompare(A, B);
173  (void)rpmdsFree(A);
174  A = NULL;
175  (void)rpmdsFree(B);
176  B = NULL;
177  }
178  one = _free(one);
179  two = _free(two);
180  return rc;
181 }
182 
183 /*@unchecked@*/
185 /*@unchecked@*/
187 /*@unchecked@*/
189 
198 static int rpmtsAddUpgrades(rpmts ts, rpmte p, rpmuint32_t hcolor, Header h)
199  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
200  /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/
201 {
202  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
203  rpmuint32_t tscolor = rpmtsColor(ts);
204  alKey pkgKey = rpmteAddedKey(p);
205  rpmuint32_t ohcolor;
206  rpmmi mi;
207  Header oh;
208  int xx;
209 
210  if (_upgrade_tag == 0) {
211  const char * t = rpmExpand("%{?_upgrade_tag}", NULL);
212 /*@-mods@*/
213  _upgrade_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
214 /*@=mods@*/
215  t = _free(t);
216  }
217 
218  mi = rpmtsInitIterator(ts, _upgrade_tag, rpmteN(p), 0);
219  while((oh = rpmmiNext(mi)) != NULL) {
220  int lastx;
221  rpmte q;
222 
223  /* Ignore colored packages not in our rainbow. */
224  ohcolor = hGetColor(oh);
225  if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
226  continue;
227 
228  /* Snarf the original install tid & time from older package(s). */
229  he->tag = RPMTAG_ORIGINTID;
230  xx = headerGet(oh, he, 0);
231  if (xx && he->p.ui32p != NULL) {
232  if (p->originTid[0] == 0 || p->originTid[0] > he->p.ui32p[0]
233  || (he->c > 1 && p->originTid[0] == he->p.ui32p[0] && p->originTid[1] > he->p.ui32p[1]))
234  {
235  p->originTid[0] = he->p.ui32p[0];
236  p->originTid[1] = (he->c > 1 ? he->p.ui32p[1] : 0);
237  }
238  he->p.ptr = _free(he->p.ptr);
239  }
240  he->tag = RPMTAG_ORIGINTIME;
241  xx = headerGet(oh, he, 0);
242  if (xx && he->p.ui32p != NULL) {
243  if (p->originTime[0] == 0 || p->originTime[0] > he->p.ui32p[0]
244  || (he->c > 1 && p->originTime[0] == he->p.ui32p[0] && p->originTime[1] > he->p.ui32p[1]))
245  {
246  p->originTime[0] = he->p.ui32p[0];
247  p->originTime[1] = (he->c > 1 ? he->p.ui32p[1] : 0);
248  }
249  he->p.ptr = _free(he->p.ptr);
250  }
251 
252 #if defined(RPM_VENDOR_WINDRIVER)
253  /*
254  * If we're capable of installing multiple colors
255  * but at least one of the packages are white (0), we
256  * further verify the arch is the same (or compatible) to trigger an upgrade
257  * we do have a special case to allow upgrades of noarch w/ a arch package
258  */
259  if (tscolor && (!hcolor || !ohcolor)) {
260  const char * arch;
261  const char * oharch;
262  he->tag = RPMTAG_ARCH;
263  xx = headerGet(h, he, 0);
264  arch = (xx && he->p.str != NULL ? he->p.str : NULL);
265  he->tag = RPMTAG_ARCH;
266  xx = headerGet(oh, he, 0);
267  oharch = (xx && he->p.str != NULL ? he->p.str : NULL);
268  if (arch != NULL && oharch != NULL) {
269  if (strcmp("noarch", arch) || strcmp("noarch", oharch)) {
270  if (!_isCompatibleArch(arch, oharch)) {
271  arch = _free(arch);
272  oharch = _free(oharch);
273  continue;
274  }
275  }
276  }
277  arch = _free(arch);
278  oharch = _free(oharch);
279  }
280 #endif
281 
282  /* Skip identical packages. */
283  if (rpmHeadersIdentical(h, oh))
284  continue;
285 
286  /* Create an erasure element. */
287  lastx = -1;
288  xx = removePackage(ts, oh, rpmmiInstance(mi), &lastx, pkgKey);
289 assert(lastx >= 0 && lastx < ts->orderCount);
290  q = ts->order[lastx];
291 
292  /* Chain through upgrade flink. */
293  xx = rpmteChain(p, q, oh, "Upgrades");
294 
295 /*@-nullptrarith@*/
296  rpmlog(RPMLOG_DEBUG, D_(" upgrade erases %s\n"), rpmteNEVRA(q));
297 /*@=nullptrarith@*/
298 
299  }
300  mi = rpmmiFree(mi);
301 
302  return 0;
303 }
304 
311 static inline int chkSuffix(const char * fn, const char * suffix)
312  /*@*/
313 {
314  size_t flen = strlen(fn);
315  size_t slen = strlen(suffix);
316  return (flen > slen && !strcmp(fn + flen - slen, suffix));
317 }
318 
327 static int rpmtsEraseDebuginfo(rpmts ts, rpmte p, Header h,
328  /*@exposed@*/ /*@dependent@*/ /*@null@*/ alKey pkgKey)
329  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
330  /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/
331 {
332  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
333  const void *keyval = NULL;
334  size_t keylen = 0;
335  size_t nrefs = 0;
336  rpmuint32_t debuginfoInstance = 0;
337  Header debuginfoHeader = NULL;
338  rpmmi mi;
339  Header oh;
340  int xx;
341 
342  /* XXX SOURCEPKGID is not populated reliably, do not use (yet). */
343  if (_debuginfo_tag == 0) {
344  const char * t = rpmExpand("%{?_debuginfo_tag}", NULL);
345 /*@-mods@*/
346  _debuginfo_tag = (*t != '\0' && !strcmp(t, "pkgid")
348 /*@=mods@*/
349  t = _free(t);
350  }
351 
352  /* Grab the retrieval key. */
353  switch (_debuginfo_tag) {
354  default: return 0; /*@notreached@*/ break;
355  case RPMTAG_SOURCERPM: keyval = rpmteSourcerpm(p); break;
356  }
357 
358  /* Count remaining members in build set, excluding -debuginfo (if any). */
359  mi = rpmtsInitIterator(ts, _debuginfo_tag, keyval, keylen);
360  xx = rpmmiPrune(mi, ts->removedPackages, ts->numRemovedPackages, 1);
361  while((oh = rpmmiNext(mi)) != NULL) {
362  /* Skip identical packages. */
363  if (rpmHeadersIdentical(h, oh))
364  continue;
365 
366  he->tag = RPMTAG_NAME;
367  xx = headerGet(oh, he, 0);
368  if (!xx || he->p.str == NULL)
369  continue;
370  /* Save the -debuginfo member. */
371  if (chkSuffix(he->p.str, "-debuginfo")) {
372  debuginfoInstance = rpmmiInstance(mi);
373  debuginfoHeader = headerLink(oh);
374  } else
375  nrefs++;
376  he->p.str = _free(he->p.str);
377  }
378  mi = rpmmiFree(mi);
379 
380  /* Remove -debuginfo package when last build member is erased. */
381  if (nrefs == 0 && debuginfoInstance > 0 && debuginfoHeader != NULL) {
382  int lastx = -1;
383  rpmte q;
384 
385  /* Create an erasure element. */
386  lastx = -1;
387  xx = removePackage(ts, debuginfoHeader, debuginfoInstance,
388  &lastx, pkgKey);
389 assert(lastx >= 0 && lastx < ts->orderCount);
390  q = ts->order[lastx];
391 
392  /* Chain through upgrade flink. */
393  /* XXX avoid assertion failure when erasing. */
394  if (pkgKey != RPMAL_NOMATCH)
395  xx = rpmteChain(p, q, oh, "Upgrades");
396 
397 /*@-nullptrarith@*/
398  rpmlog(RPMLOG_DEBUG, D_(" lastref erases %s\n"), rpmteNEVRA(q));
399 /*@=nullptrarith@*/
400 
401  }
402  (void)headerFree(debuginfoHeader);
403  debuginfoHeader = NULL;
404 
405  return (int)nrefs;
406 }
407 
415 static int rpmtsAddObsoletes(rpmts ts, rpmte p, rpmuint32_t hcolor)
416  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
417  /*@modifies ts, p, rpmGlobalMacroContext, fileSystem, internalState @*/
418 {
419  rpmuint32_t tscolor = rpmtsColor(ts);
420  alKey pkgKey = rpmteAddedKey(p);
421  rpmuint32_t ohcolor;
422  rpmds obsoletes;
423  rpmuint32_t dscolor;
424  rpmmi mi;
425  Header oh;
426  int xx;
427 
428  if (_obsolete_tag == 0) {
429  const char *t = rpmExpand("%{?_obsolete_tag}", NULL);
430 /*@-mods@*/
431  _obsolete_tag = (!strcmp(t, "name") ? RPMTAG_NAME : RPMTAG_PROVIDENAME);
432 /*@=mods@*/
433  t = _free(t);
434  }
435 
436  obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME), "Obsoletes");
437  obsoletes = rpmdsInit(obsoletes);
438  if (obsoletes != NULL)
439  while (rpmdsNext(obsoletes) >= 0) {
440  const char * Name;
441 
442  if ((Name = rpmdsN(obsoletes)) == NULL)
443  continue; /* XXX can't happen */
444 
445  /* Ignore colored obsoletes not in our rainbow. */
446 #if 0
447  /* XXX obsoletes are never colored, so this is for future devel. */
448  dscolor = rpmdsColor(obsoletes);
449 #else
450  dscolor = hcolor;
451 #endif
452  if (tscolor && dscolor && !(tscolor & dscolor))
453  continue;
454 
455  /* XXX avoid self-obsoleting packages. */
456  if (!strcmp(rpmteN(p), Name))
457  continue;
458 
459  /* Obsolete containing package if given a file, otherwise provide. */
460  if (Name[0] == '/')
461  mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
462  else
463  mi = rpmtsInitIterator(ts, _obsolete_tag, Name, 0);
464 
465  xx = rpmmiPrune(mi, ts->removedPackages, ts->numRemovedPackages, 1);
466 
467  while((oh = rpmmiNext(mi)) != NULL) {
468  int lastx;
469  rpmte q;
470 
471  /* Ignore colored packages not in our rainbow. */
472  ohcolor = hGetColor(oh);
473 
474  /* XXX provides *are* colored, effectively limiting Obsoletes:
475  to matching only colored Provides: based on pkg coloring. */
476  if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
477  /*@innercontinue@*/ continue;
478 
479  /*
480  * Rpm prior to 3.0.3 does not have versioned obsoletes.
481  * If no obsoletes version info is available, match all names.
482  */
483  if (!(rpmdsEVR(obsoletes) == NULL
484  || rpmdsAnyMatchesDep(oh, obsoletes, _rpmds_nopromote)))
485  /*@innercontinue@*/ continue;
486 
487  /* Create an erasure element. */
488  lastx = -1;
489  xx = removePackage(ts, oh, rpmmiInstance(mi), &lastx, pkgKey);
490 assert(lastx >= 0 && lastx < ts->orderCount);
491  q = ts->order[lastx];
492 
493  /* Chain through obsoletes flink. */
494  xx = rpmteChain(p, q, oh, "Obsoletes");
495 
496 /*@-nullptrarith@*/
497  rpmlog(RPMLOG_DEBUG, D_(" Obsoletes: %s\t\terases %s\n"),
498  rpmdsDNEVR(obsoletes)+2, rpmteNEVRA(q));
499 /*@=nullptrarith@*/
500  }
501  mi = rpmmiFree(mi);
502  }
503  (void)rpmdsFree(obsoletes);
504  obsoletes = NULL;
505 
506  return 0;
507 }
508 
509 #if defined(RPM_VENDOR_WINDRIVER)
510 /* Is "compat" compatible w/ arch? */
511 int _isCompatibleArch(const char * arch, const char * compat)
512 {
513  const char * compatArch = rpmExpand(compat, " %{?_", compat, "_compat_arch}", NULL);
514  const char * p, * pe, * t;
515  int match = 0;
516 
517  /* Hack to ensure iX86 being automatically compatible */
518  if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') {
519  if ((arch[0] == compat[0]) &&
520  (arch[2] == compat[2]) &&
521  (arch[3] == compat[3]))
522  match = 1;
523 
524  if (!strcmp(compat, "x86_32"))
525  match = 1;
526  }
527 
528  for ( p = pe = compatArch ; *pe && match == 0 ; ) {
529  while (*p && xisspace(*p)) p++;
530  pe = p ; while (*pe && !xisspace(*pe)) pe++;
531  if (p == pe)
532  break;
533  t = strndup(p, (pe - p));
534  p = pe; /* Advance to next chunk */
535 rpmlog(RPMLOG_DEBUG, D_(" Comparing compat archs %s ? %s\n"), arch, t);
536  if (!strcmp(arch, t))
537  match = 1;
538  t = _free(t);
539  }
540  compatArch = _free(compatArch);
541  return match;
542 }
543 #endif
544 
546  fnpyKey key, int upgrade, rpmRelocation relocs)
547 {
548  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
549  rpmdepFlags depFlags = rpmtsDFlags(ts);
550  rpmuint32_t tscolor = rpmtsColor(ts);
551  rpmuint32_t hcolor;
552  int isSource;
553  int duplicate = 0;
554  rpmtsi pi = NULL; rpmte p;
555  const char * arch = NULL;
556  const char * os = NULL;
557  rpmds oldChk, newChk;
558  alKey pkgKey; /* addedPackages key */
559  int xx;
560  int ec = 0;
561  int rc;
562  int oc;
563 
564  hcolor = hGetColor(h);
565  pkgKey = RPMAL_NOMATCH;
566 
567  /*
568  * Always add source headers.
569  */
570  isSource =
571  (headerIsEntry(h, RPMTAG_SOURCERPM) == 0 &&
572  headerIsEntry(h, RPMTAG_ARCH) != 0);
573  if (isSource) {
574  oc = ts->orderCount;
575  goto addheader;
576  }
577 
578  /*
579  * Check platform affinity of binary packages.
580  */
581  he->tag = RPMTAG_ARCH;
582  xx = headerGet(h, he, 0);
583  arch = he->p.str;
584  he->tag = RPMTAG_OS;
585  xx = headerGet(h, he, 0);
586  os = he->p.str;
587  if (nplatpat > 1) {
588  const char * platform = NULL;
589 
590  /*
591  * If ignore arch, we just set the arch in package platform string to
592  * same as on system so that we're sure that it'll match, same goes for
593  * os as well.
594  */
595  if (rpmExpandNumeric("%{__ignore_arch}") || rpmExpandNumeric("%{__ignore_os}")) {
596  platform = rpmExpand(
597  rpmExpandNumeric("%{__ignore_arch}") ? "%{_target_cpu}" : arch,
598  "-unknown-",
599  rpmExpandNumeric("%{__ignore_os}") ? "%{_target_os}" : os,
600  NULL);
601  } else {
602  he->tag = RPMTAG_PLATFORM;
603  xx = headerGet(h, he, 0);
604  platform = he->p.str;
605  if (!xx || platform == NULL)
606  platform = rpmExpand(arch, "-unknown-", os, NULL);
607  }
608 
609  rc = rpmPlatformScore(platform, platpat, nplatpat);
610 #if defined(RPM_VENDOR_MANDRIVA)
611  /*
612  * If no match on platform tag, we'll try again with arch tag
613  * in case platform tag is inconsistent with it, which is the case
614  * for older noarch sub-packages built (mdvbz#61746).
615  */
616  if(xx && rc <= 0) {
617  platform = _free(platform);
618  platform = rpmExpand(arch, "-unknown-", os, NULL);
619  rc = rpmPlatformScore(platform, platpat, nplatpat);
620  }
621 #endif
622  if (rc <= 0) {
623  rpmps ps = rpmtsProblems(ts);
624  he->tag = RPMTAG_NVRA;
625  xx = headerGet(h, he, 0);
626 assert(he->p.str != NULL);
627 
628  rpmpsAppend(ps, RPMPROB_BADPLATFORM, he->p.str, key,
629  platform, NULL, NULL, 0);
630 
631  /* XXX problem string should be printed by caller instead. */
632  if (rpmIsVerbose()) {
633  const char * msg = rpmProblemString(rpmpsGetProblem(ps, -1));
634  rpmlog(RPMLOG_WARNING, "%s\n", msg);
635  msg = _free(msg);
636  }
637 
638  ps = rpmpsFree(ps);
639  he->p.ptr = _free(he->p.ptr);
640  ec = 1;
641  }
642  platform = _free(platform);
643  if (ec)
644  goto exit;
645  }
646 
647  /*
648  * Always install compatible binary packages.
649  */
650  if (!upgrade) {
651  oc = ts->orderCount;
652  goto addheader;
653  }
654 
655  /*
656  * Check that upgrade package is uniquely newer, replace older if necessary.
657  */
660  /* XXX can't use rpmtsiNext() filter or oc will have wrong value. */
661  for (pi = rpmtsiInit(ts), oc = 0; (p = rpmtsiNext(pi, (rpmElementType)0)) != NULL; oc++) {
662  rpmds ds;
663 
664  /* XXX Only added packages need be checked for dupes here. */
665  if (rpmteType(p) == TR_REMOVED)
666  continue;
667 
668  /* XXX Never check source header NEVRAO. */
669  if (rpmteIsSource(p))
670  continue;
671 
672  if (tscolor) {
673  const char * parch;
674  const char * pos;
675 
676  if (arch == NULL || (parch = rpmteA(p)) == NULL)
677  continue;
678 #if defined(RPM_VENDOR_WINDRIVER)
679  /* XXX hackery for alias matching. */
680  if (!_isCompatibleArch(arch, parch))
681  continue;
682 #else
683  /* XXX hackery for i[3456]86 alias matching. */
684  if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') {
685  if (arch[0] != parch[0]) continue;
686  if (arch[2] != parch[2]) continue;
687  if (arch[3] != parch[3]) continue;
688  }
689 #endif
690  else if (strcmp(arch, parch))
691  continue;
692  if (os == NULL || (pos = rpmteO(p)) == NULL)
693  continue;
694 
695  if (strcmp(os, pos))
696  continue;
697  }
698 
699  /* OK, binary rpm's with same arch and os. Check NEVR. */
700  if ((ds = rpmteDS(p, RPMTAG_NAME)) == NULL)
701  continue; /* XXX can't happen */
702 
703  /* If newer NEVRAO already added, then skip adding older. */
704  rc = rpmdsCompare(newChk, ds);
705  if (rc != 0) {
706  const char * pkgNEVR = rpmdsDNEVR(ds);
707  const char * addNEVR = rpmdsDNEVR(oldChk);
708  if (rpmIsVerbose())
710  _("package %s was already added, skipping %s\n"),
711  (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
712  (addNEVR ? addNEVR + 2 : "?addNEVR?"));
713  ec = 1;
714  break;
715  }
716 
717  /* If older NEVRAO already added, then replace old with new. */
718  rc = rpmdsCompare(oldChk, ds);
719  if (rc != 0) {
720  const char * pkgNEVR = rpmdsDNEVR(ds);
721  const char * addNEVR = rpmdsDNEVR(newChk);
722  if (rpmIsVerbose())
724  _("package %s was already added, replacing with %s\n"),
725  (pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
726  (addNEVR ? addNEVR + 2 : "?addNEVR?"));
727  duplicate = 1;
728  pkgKey = rpmteAddedKey(p);
729  break;
730  }
731  }
732  pi = rpmtsiFree(pi);
733  (void)rpmdsFree(oldChk);
734  oldChk = NULL;
735  (void)rpmdsFree(newChk);
736  newChk = NULL;
737 
738  /* If newer (or same) NEVRAO was already added, exit now. */
739  if (ec)
740  goto exit;
741 
742 addheader:
743  if (oc >= ts->orderAlloced) {
744  ts->orderAlloced += (oc - ts->orderAlloced) + ts->delta;
745 /*@-type +voidabstract @*/
746  ts->order = (rpmte *) xrealloc(ts->order, ts->orderAlloced * sizeof(*ts->order));
747 /*@=type =voidabstract @*/
748  }
749 
750  p = rpmteNew(ts, h, TR_ADDED, key, relocs, -1, pkgKey);
751 assert(p != NULL);
752 
753  if (duplicate && oc < ts->orderCount) {
754  ts->numAddedFiles -= rpmfiFC(rpmteFI(ts->order[oc], RPMTAG_BASENAMES));
755 /*@-type -unqualifiedtrans@*/
756  ts->order[oc] = rpmteFree(ts->order[oc]);
757 /*@=type =unqualifiedtrans@*/
758  }
759 
760  ts->order[oc] = p;
761  ts->numAddedFiles += rpmfiFC(rpmteFI(p, RPMTAG_BASENAMES));
762  if (!duplicate) {
763  ts->orderCount++;
765  }
766 
767  pkgKey = rpmalAdd(&ts->addedPackages, pkgKey, rpmteKey(p),
769  rpmteFI(p, RPMTAG_BASENAMES), tscolor);
770  if (pkgKey == RPMAL_NOMATCH) {
771  ts->order[oc] = rpmteFree(ts->order[oc]);
772  ts->teInstall = NULL;
773  ec = 1;
774  goto exit;
775  }
776  (void) rpmteSetAddedKey(p, pkgKey);
777 
778  if (!duplicate) {
779  ts->numAddedPackages++;
780  }
781 
782  ts->teInstall = ts->order[oc];
783 
784  /* XXX rpmgi hack: Save header in transaction element if requested. */
785  if (upgrade & 0x2)
786  (void) rpmteSetHeader(p, h);
787 
788  /* If not upgrading, then we're done. */
789  if (!(upgrade & 0x1))
790  goto exit;
791 
792  /* If source rpm, then we're done. */
793  if (isSource)
794  goto exit;
795 
796  /* Do lazy (readonly?) open of rpm database. */
797  if (rpmtsGetRdb(ts) == NULL && rpmtsDBMode(ts) != -1) {
798  if ((ec = rpmtsOpenDB(ts, rpmtsDBMode(ts)) != 0))
799  goto exit;
800  }
801 
802  /* Add upgrades to the transaction (if not disabled). */
803  if (!(depFlags & RPMDEPS_FLAG_NOUPGRADE)) {
804  /*
805  * Don't upgrade -debuginfo until build set is empty.
806  *
807  * XXX Almost, but not quite, correct since the test depends on
808  * added package arrival order.
809  * I.e. -debuginfo additions must always follow all
810  * other additions so that erasures of other members in the
811  * same build set are seen if/when included in the same transaction.
812  */
813  xx = rpmtsEraseDebuginfo(ts, p, h, pkgKey);
814  if (!chkSuffix(rpmteN(p), "-debuginfo") || xx == 0)
815  xx = rpmtsAddUpgrades(ts, p, hcolor, h);
816  }
817 
818  /* Add Obsoletes: to the transaction (if not disabled). */
819  if (!(depFlags & RPMDEPS_FLAG_NOOBSOLETES)) {
820  xx = rpmtsAddObsoletes(ts, p, hcolor);
821  }
822 
823  ec = 0;
824 
825 exit:
826  arch = _free(arch);
827  os = _free(os);
828  pi = rpmtsiFree(pi);
829  return ec;
830 }
831 
832 int rpmtsAddEraseElement(rpmts ts, Header h, uint32_t hdrNum)
833 {
834  int oc = -1;
835  int rc = removePackage(ts, h, hdrNum, &oc, RPMAL_NOMATCH);
836  if (rc == 0 && oc >= 0 && oc < ts->orderCount) {
837  (void) rpmtsEraseDebuginfo(ts, ts->order[oc], h, RPMAL_NOMATCH);
838  ts->teErase = ts->order[oc];
839  } else
840  ts->teErase = NULL;
841  return rc;
842 }
843 
844 /*@only@*/ /*@null@*/ /*@unchecked@*/
845 static char *sysinfo_path = NULL;
846 
847 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/
848 static rpmds rpmlibP = NULL;
849 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/
851 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/
852 static rpmds getconfP = NULL;
853 /*@refcounted@*/ /*@null@*/ /*@unchecked@*/
854 static rpmds unameP = NULL;
855 
856 void rpmnsClean(void)
857  /*@globals sysinfo_path, _sysinfo_path, rpmlibP, cpuinfoP, getconfP, unameP @*/
858  /*@modifies sysinfo_path, _sysinfo_path, rpmlibP, cpuinfoP, getconfP, unameP @*/
859 {
860  (void)rpmdsFree(rpmlibP);
861  rpmlibP = NULL;
862  (void)rpmdsFree(cpuinfoP);
863  cpuinfoP = NULL;
864  (void)rpmdsFree(getconfP);
865  getconfP = NULL;
866  (void)rpmdsFree(unameP);
867  unameP = NULL;
868 /*@-observertrans@*/
870 /*@=observertrans@*/
871  sysinfo_path = _free(sysinfo_path);
872 }
873 
881 static int unsatisfiedDepend(rpmts ts, rpmds dep, int adding)
882  /*@globals _cacheDependsRC, rpmGlobalMacroContext, h_errno,
883  sysinfo_path, fileSystem, internalState @*/
884  /*@modifies ts, dep, _cacheDependsRC, rpmGlobalMacroContext,
885  sysinfo_path, fileSystem, internalState @*/
886 {
887  DBT * key = (DBT *) alloca(sizeof(*key));
888  DBT * data = (DBT *) alloca(sizeof(*data));
889  rpmmi mi;
890  nsType NSType;
891  const char * Name;
892  rpmuint32_t Flags;
893  Header h;
894 #if defined(CACHE_DEPENDENCY_RESULT)
895  int _cacheThisRC = 1;
896 #endif
897  int rc;
898  int xx;
899  int retries = 20;
900 
901  if ((Name = rpmdsN(dep)) == NULL)
902  return 0; /* XXX can't happen */
903  Flags = rpmdsFlags(dep);
904  NSType = rpmdsNSType(dep);
905 
906 #if defined(CACHE_DEPENDENCY_RESULT)
907  /*
908  * Check if dbiOpen/dbiPut failed (e.g. permissions), we can't cache.
909  */
910  if (_cacheDependsRC) {
911  dbiIndex dbi;
912  dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPCACHE, 0);
913  if (dbi == NULL)
914  _cacheDependsRC = 0;
915  else {
916  const char * DNEVR;
917 
918  rc = -1;
919  if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
920  DBC * dbcursor = NULL;
921  void * datap = NULL;
922  size_t datalen = 0;
923  size_t DNEVRlen = strlen(DNEVR);
924 
925  xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, 0);
926 
927  memset(key, 0, sizeof(*key));
928 /*@i@*/ key->data = (void *) DNEVR;
929  key->size = DNEVRlen;
930  memset(data, 0, sizeof(*data));
931  data->data = datap;
932  data->size = datalen;
933 /*@-nullstate@*/ /* FIX: data->data may be NULL */
934  xx = dbiGet(dbi, dbcursor, key, data, DB_SET);
935 /*@=nullstate@*/
936  DNEVR = (char *) key->data;
937  DNEVRlen = key->size;
938  datap = data->data;
939  datalen = data->size;
940 
941  if (xx == 0 && datap && datalen == 4)
942  memcpy(&rc, datap, datalen);
943  xx = dbiCclose(dbi, dbcursor, 0);
944  }
945 
946  if (rc >= 0) {
947  rpmdsNotify(dep, _("(cached)"), rc);
948  return rpmdsNegateRC(dep, rc);
949  }
950  }
951  }
952 #endif
953 
954 retry:
955  rc = 0; /* assume dependency is satisfied */
956 
957  /* Expand macro probe dependencies. */
958  if (NSType == RPMNS_TYPE_FUNCTION) {
959  xx = rpmExpandNumeric(Name);
960  rc = (xx ? 0 : 1);
961  if (Flags & RPMSENSE_MISSINGOK)
962  goto unsatisfied;
963  rpmdsNotify(dep, _("(function probe)"), rc);
964  goto exit;
965  }
966 
967  /* Evaluate user/group lookup probes. */
968  if (NSType == RPMNS_TYPE_USER) {
969  const char *s;
970  uid_t uid = 0;
971  s = Name; while (*s && xisdigit(*s)) s++;
972 
973  if (*s)
974  xx = unameToUid(Name, &uid);
975  else {
976  uid = strtol(Name, NULL, 10);
977  xx = (uidToUname(uid) ? 0 : -1);
978  }
979  rc = (xx >= 0 ? 0 : 1);
980  if (Flags & RPMSENSE_MISSINGOK)
981  goto unsatisfied;
982  rpmdsNotify(dep, _("(user lookup)"), rc);
983  goto exit;
984  }
985  if (NSType == RPMNS_TYPE_GROUP) {
986  const char *s;
987  gid_t gid = 0;
988  s = Name; while (*s && xisdigit(*s)) s++;
989 
990  if (*s)
991  xx = gnameToGid(Name, &gid);
992  else {
993  gid = strtol(Name, NULL, 10);
994  xx = (gidToGname(gid) ? 0 : -1);
995  }
996  rc = (xx >= 0 ? 0 : 1);
997  if (Flags & RPMSENSE_MISSINGOK)
998  goto unsatisfied;
999  rpmdsNotify(dep, _("(group lookup)"), rc);
1000  goto exit;
1001  }
1002 
1003  /* Evaluate access(2) probe dependencies. */
1004  if (NSType == RPMNS_TYPE_ACCESS) {
1005  rc = rpmioAccess(Name, NULL, X_OK);
1006  if (Flags & RPMSENSE_MISSINGOK)
1007  goto unsatisfied;
1008  rpmdsNotify(dep, _("(access probe)"), rc);
1009  goto exit;
1010  }
1011 
1012  /* Evaluate mtab lookup and diskspace probe dependencies. */
1013  if (NSType == RPMNS_TYPE_MOUNTED) {
1014  const char ** fs = NULL;
1015  int nfs = 0;
1016  int i = 0;
1017 
1018  xx = rpmtsInitDSI(ts);
1019  fs = ts->filesystems;
1020  nfs = ts->filesystemCount;
1021 
1022  if (fs != NULL)
1023  for (i = 0; i < nfs; i++) {
1024  if (!strcmp(fs[i], Name))
1025  break;
1026  }
1027  rc = (i < nfs ? 0 : 1);
1028  if (Flags & RPMSENSE_MISSINGOK)
1029  goto unsatisfied;
1030  rpmdsNotify(dep, _("(mtab probe)"), rc);
1031  goto exit;
1032  }
1033 
1034  if (NSType == RPMNS_TYPE_DISKSPACE) {
1035  size_t nb = strlen(Name);
1036  rpmDiskSpaceInfo dsi = NULL;
1037  const char ** fs = NULL;
1038  size_t fslen = 0, longest = 0;
1039  int nfs = 0;
1040  int i = 0;
1041 
1042  xx = rpmtsInitDSI(ts);
1043  fs = ts->filesystems;
1044  nfs = ts->filesystemCount;
1045 
1046  if (fs != NULL)
1047  for (i = 0; i < nfs; i++) {
1048  fslen = strlen(fs[i]);
1049  if (fslen > nb)
1050  continue;
1051  if (strncmp(fs[i], Name, fslen))
1052  continue;
1053  if (fslen > 1 && Name[fslen] != '/' && Name[fslen] != '\0')
1054  continue;
1055  if (fslen < longest)
1056  continue;
1057  longest = fslen;
1058  dsi = ts->dsi + i;
1059  }
1060  if (dsi == NULL)
1061  rc = 1; /* no mounted paths !?! */
1062  else {
1063  char * end = NULL;
1064 /*@-unrecog@*/
1065  rpmuint64_t needed = strtoll(rpmdsEVR(dep), &end, 0);
1066 /*@=unrecog@*/
1067 
1068  if (end && *end) {
1069  if (strchr("Gg", end[0]) && strchr("Bb", end[1]) && !end[2])
1070  needed *= 1024 * 1024 * 1024;
1071  if (strchr("Mm", end[0]) && strchr("Bb", end[1]) && !end[2])
1072  needed *= 1024 * 1024;
1073  if (strchr("Kk", end[0]) && strchr("Bb", end[1]) && !end[2])
1074  needed *= 1024;
1075  } else
1076  needed *= 1024 * 1024; /* XXX assume Mb if no units given */
1077 
1078  needed = BLOCK_ROUND(needed, dsi->f_bsize);
1079  xx = (dsi->f_bavail - needed);
1080  if ((Flags & RPMSENSE_LESS) && xx < 0) rc = 0;
1081  else if ((Flags & RPMSENSE_GREATER) && xx > 0) rc = 0;
1082  else if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
1083  else rc = 1;
1084  }
1085  if (Flags & RPMSENSE_MISSINGOK)
1086  goto unsatisfied;
1087  rpmdsNotify(dep, _("(diskspace probe)"), rc);
1088  goto exit;
1089  }
1090 
1091  if (NSType == RPMNS_TYPE_DIGEST) {
1092  const char * EVR = rpmdsEVR(dep);
1093  const char *filename;
1094  pgpHashAlgo digestHashAlgo;
1095  FD_t fd;
1096  char *cp;
1097  pgpHashAlgo algo;
1098 
1099  filename = Name;
1100  digestHashAlgo = PGPHASHALGO_MD5;
1101  if ((cp = (char *) strchr(filename, ':')) != NULL) {
1102  if ((algo = pgpHashAlgoStringToNumber(filename, cp-filename)) != PGPHASHALGO_ERROR) {
1103  digestHashAlgo = algo;
1104  filename = cp + 1;
1105  }
1106  }
1107  rc = 1; /* XXX assume failure */
1108  fd = Fopen(filename, "r.fdio");
1109  if (fd && !Ferror(fd)) {
1110  DIGEST_CTX ctx = rpmDigestInit(digestHashAlgo, RPMDIGEST_NONE);
1111  const char * digest = NULL;
1112  size_t digestlen = 0;
1113  int asAscii = 1;
1114  size_t nbuf = 8 * BUFSIZ;
1115  char * buf = (char *) alloca(nbuf);
1116  size_t nb;
1117 
1118  while ((nb = Fread(buf, sizeof(buf[0]), nbuf, fd)) > 0)
1119  xx = rpmDigestUpdate(ctx, buf, nb);
1120  xx = Fclose(fd); fd = NULL;
1121  xx = rpmDigestFinal(ctx, &digest, &digestlen, asAscii);
1122 
1123  xx = (EVR && *EVR && digest && *digest) ? strcasecmp(EVR, digest) : -1;
1124  /* XXX only equality makes sense for digest compares */
1125  if ((Flags & RPMSENSE_EQUAL) && xx == 0) rc = 0;
1126  }
1127  if (Flags & RPMSENSE_MISSINGOK)
1128  goto unsatisfied;
1129  rpmdsNotify(dep, _("(digest probe)"), rc);
1130  goto exit;
1131  }
1132 
1133  if (NSType == RPMNS_TYPE_SIGNATURE) {
1134  const char * EVR = rpmdsEVR(dep);
1135  ARGV_t avN = NULL;
1136  ARGV_t avEVR = NULL;
1137  rpmRC res;
1138 
1139  /* Split /fn:/sig */
1140  xx = argvSplit(&avN, Name, ":");
1141 
1142  /* Split /pub:id */
1143  xx = (EVR && *EVR) ? argvSplit(&avEVR, EVR, ":") : argvAdd(&avEVR, "");
1144 
1145  res = rpmnsProbeSignature(ts, avN[0], avN[1], avEVR[0], avEVR[1], 0);
1146  rc = (res == RPMRC_OK ? 0 : 1);
1147 
1148  avN = argvFree(avN);
1149  avEVR = argvFree(avEVR);
1150 
1151  if (Flags & RPMSENSE_MISSINGOK)
1152  goto unsatisfied;
1153  rpmdsNotify(dep, _("(signature probe)"), rc);
1154  goto exit;
1155  }
1156 
1157  if (NSType == RPMNS_TYPE_VERIFY) {
1158  QVA_t qva = (QVA_t) memset(alloca(sizeof(*qva)), 0, sizeof(*qva));
1159 
1160  qva->qva_mode = 'v';
1161  qva->qva_flags = (rpmQueryFlags)
1163  rc = 0; /* assume success */
1164  if (rpmtsGetRdb(ts) != NULL) {
1165  if (!strcmp(Name, "*")) /* -Va probe */
1166  mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, NULL, 0);
1167  else if (Name[0] == '/') /* -Vf probe */
1168  mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
1169  else /* -V probe */
1170  mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
1171  while ((h = rpmmiNext(mi)) != NULL) {
1172  if (!(Name[0] == '/' || !strcmp(Name, "*")))
1173  if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote))
1174  continue;
1175  xx = (showVerifyPackage(qva, ts, h) ? 1 : 0);
1176  if (xx)
1177  rc = 1;
1178  }
1179  mi = rpmmiFree(mi);
1180  }
1181 
1182  if (Flags & RPMSENSE_MISSINGOK)
1183  goto unsatisfied;
1184  rpmdsNotify(dep, _("(verify probe)"), rc);
1185  goto exit;
1186  }
1187 
1188  if (NSType == RPMNS_TYPE_GNUPG) {
1189  const char * EVR = rpmdsEVR(dep);
1190  if (!(EVR && *EVR)) {
1191  static const char gnupg_pre[] = "%(%{__gpg} --batch --no-tty --quiet --verify ";
1192  static const char gnupg_post[] = " 2>/dev/null; echo $?)";
1193  const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL);
1194  rc = (t && t[0] == '0') ? 0 : 1;
1195  t = _free(t);
1196  }
1197  else {
1198  static const char gnupg_pre[] = "%(%{__gpg} --batch --no-tty --quiet --verify ";
1199  static const char gnupg_post[] = " 2>&1 | grep '^Primary key fingerprint:' | sed -e 's;^.*: *;;' -e 's; *;;g')";
1200  const char * t = rpmExpand(gnupg_pre, Name, gnupg_post, NULL);
1201  rc = ((Flags & RPMSENSE_EQUAL) && strcasecmp(EVR, t) == 0) ? 0 : 1;
1202  t = _free(t);
1203  }
1204  if (Flags & RPMSENSE_MISSINGOK)
1205  goto unsatisfied;
1206  rpmdsNotify(dep, _("(gnupg probe)"), rc);
1207  goto exit;
1208  }
1209 
1210  if (NSType == RPMNS_TYPE_MACRO) {
1211  static const char macro_pre[] = "%{?";
1212  static const char macro_post[] = ":0}";
1213  const char * a = rpmExpand(macro_pre, Name, macro_post, NULL);
1214 
1215  rc = (a && a[0] == '0') ? 0 : 1;
1216  a = _free(a);
1217  if (Flags & RPMSENSE_MISSINGOK)
1218  goto unsatisfied;
1219  rpmdsNotify(dep, _("(macro probe)"), rc);
1220  goto exit;
1221  }
1222 
1223  if (NSType == RPMNS_TYPE_ENVVAR) {
1224  const char * a = envGet(Name);
1225  const char * b = rpmdsEVR(dep);
1226 
1227  /* Existence test if EVR is missing/empty. */
1228  if (!(b && *b))
1229  rc = (!(a && *a));
1230  else {
1231  int sense = (a && *a) ? strcmp(a, b) : -1;
1232 
1233  if ((Flags & RPMSENSE_SENSEMASK) == RPMSENSE_NOTEQUAL)
1234  rc = (sense == 0);
1235  else if (sense < 0 && (Flags & RPMSENSE_LESS))
1236  rc = 0;
1237  else if (sense > 0 && (Flags & RPMSENSE_GREATER))
1238  rc = 0;
1239  else if (sense == 0 && (Flags & RPMSENSE_EQUAL))
1240  rc = 0;
1241  else
1242  rc = (sense != 0);
1243  }
1244 
1245  if (Flags & RPMSENSE_MISSINGOK)
1246  goto unsatisfied;
1247  rpmdsNotify(dep, _("(envvar probe)"), rc);
1248  goto exit;
1249  }
1250 
1251  if (NSType == RPMNS_TYPE_RUNNING) {
1252  char *t = NULL;
1253  pid_t pid = strtol(Name, &t, 10);
1254 
1255  if (t == NULL || *t != '\0') {
1256  const char * fn = rpmGetPath("%{_varrun}/", Name, ".pid", NULL);
1257  FD_t fd = NULL;
1258 
1259  if (fn && *fn != '%' && (fd = Fopen(fn, "r.fdio")) && !Ferror(fd)) {
1260  char buf[32];
1261  size_t nb = Fread(buf, sizeof(buf[0]), sizeof(buf), fd);
1262 
1263  if (nb > 0)
1264  pid = strtol(buf, &t, 10);
1265  } else
1266  pid = 0;
1267  if (fd != NULL)
1268  (void) Fclose(fd);
1269  fn = _free(fn);
1270  }
1271  rc = (pid > 0 ? (kill(pid, 0) < 0 && errno == ESRCH) : 1);
1272  if (Flags & RPMSENSE_MISSINGOK)
1273  goto unsatisfied;
1274  rpmdsNotify(dep, _("(running probe)"), rc);
1275  goto exit;
1276  }
1277 
1278  if (NSType == RPMNS_TYPE_SANITY) {
1279  /* XXX only the installer does not have the database open here. */
1280  rc = 1; /* assume failure */
1281  if (rpmtsGetRdb(ts) != NULL) {
1282  mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
1283  while ((h = rpmmiNext(mi)) != NULL) {
1284  if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote))
1285  continue;
1286  rc = (headerIsEntry(h, RPMTAG_SANITYCHECK) == 0);
1287  if (rc == 0) {
1288  /* XXX FIXME: actually run the sanitycheck script. */
1289  break;
1290  }
1291  }
1292  mi = rpmmiFree(mi);
1293  }
1294  if (Flags & RPMSENSE_MISSINGOK)
1295  goto unsatisfied;
1296  rpmdsNotify(dep, _("(sanity probe)"), rc);
1297  goto exit;
1298  }
1299 
1300  if (NSType == RPMNS_TYPE_VCHECK) {
1301  rc = 1; /* assume failure */
1302  if (rpmtsGetRdb(ts) != NULL) {
1303  mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
1304  while ((h = rpmmiNext(mi)) != NULL) {
1305  if (!rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote))
1306  continue;
1307  rc = (headerIsEntry(h, RPMTAG_TRACK) == 0);
1308  if (rc == 0) {
1309  /* XXX FIXME: actually run the vcheck script. */
1310  break;
1311  }
1312  }
1313  mi = rpmmiFree(mi);
1314  }
1315  if (Flags & RPMSENSE_MISSINGOK)
1316  goto unsatisfied;
1317  rpmdsNotify(dep, _("(vcheck probe)"), rc);
1318  goto exit;
1319  }
1320 
1321  /* Search system configured provides. */
1322  if (sysinfo_path == NULL) {
1323  sysinfo_path = rpmExpand("%{?_rpmds_sysinfo_path}", NULL);
1324  if (!(sysinfo_path != NULL && *sysinfo_path == '/')) {
1325  sysinfo_path = _free(sysinfo_path);
1326  sysinfo_path = xstrdup(SYSCONFIGDIR "/sysinfo");
1327  }
1328  }
1329 
1330  if (!rpmioAccess(sysinfo_path, NULL, R_OK)) {
1331 #ifdef NOTYET /* XXX just sysinfo Provides: for now. */
1332  rpmTag tagN = (Name[0] == '/' ? RPMTAG_DIRNAMES : RPMTAG_PROVIDENAME);
1333 #else
1334  rpmTag tagN = RPMTAG_PROVIDENAME;
1335 #endif
1336  rpmds P = rpmdsFromPRCO(rpmtsPRCO(ts), tagN);
1337  if (rpmdsSearch(P, dep) >= 0) {
1338  rpmdsNotify(dep, _("(sysinfo provides)"), rc);
1339  goto exit;
1340  }
1341  }
1342 
1343  /*
1344  * New features in rpm packaging implicitly add versioned dependencies
1345  * on rpmlib provides. The dependencies look like "rpmlib(YaddaYadda)".
1346  * Check those dependencies now.
1347  */
1348  if (NSType == RPMNS_TYPE_RPMLIB) {
1349  static int oneshot = -1;
1350 
1351  if (oneshot)
1352  oneshot = rpmdsRpmlib(&rpmlibP, NULL);
1353  if (rpmlibP == NULL)
1354  goto unsatisfied;
1355 
1356  if (rpmdsSearch(rpmlibP, dep) >= 0) {
1357  rpmdsNotify(dep, _("(rpmlib provides)"), rc);
1358  goto exit;
1359  }
1360  goto unsatisfied;
1361  }
1362 
1363  if (NSType == RPMNS_TYPE_CPUINFO) {
1364  static int oneshot = -1;
1365 
1366  if (oneshot && cpuinfoP == NULL)
1367  oneshot = rpmdsCpuinfo(&cpuinfoP, NULL);
1368  if (cpuinfoP == NULL)
1369  goto unsatisfied;
1370 
1371  if (rpmdsSearch(cpuinfoP, dep) >= 0) {
1372  rpmdsNotify(dep, _("(cpuinfo provides)"), rc);
1373  goto exit;
1374  }
1375  goto unsatisfied;
1376  }
1377 
1378  if (NSType == RPMNS_TYPE_GETCONF) {
1379  static int oneshot = -1;
1380 
1381  if (oneshot)
1382  oneshot = rpmdsGetconf(&getconfP, NULL);
1383  if (getconfP == NULL)
1384  goto unsatisfied;
1385 
1386  if (rpmdsSearch(getconfP, dep) >= 0) {
1387  rpmdsNotify(dep, _("(getconf provides)"), rc);
1388  goto exit;
1389  }
1390  goto unsatisfied;
1391  }
1392 
1393  if (NSType == RPMNS_TYPE_UNAME) {
1394  static int oneshot = -1;
1395 
1396  if (oneshot)
1397  oneshot = rpmdsUname(&unameP, NULL);
1398  if (unameP == NULL)
1399  goto unsatisfied;
1400 
1401  if (rpmdsSearch(unameP, dep) >= 0) {
1402  rpmdsNotify(dep, _("(uname provides)"), rc);
1403  goto exit;
1404  }
1405  goto unsatisfied;
1406  }
1407 
1408  if (NSType == RPMNS_TYPE_SONAME) {
1409  rpmds sonameP = NULL;
1410  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
1411  char * fn = strcpy((char *)alloca(strlen(Name)+1), Name);
1412  int flags = 0; /* XXX RPMELF_FLAG_SKIPREQUIRES? */
1413  rpmds ds;
1414 
1415  /* XXX Only absolute paths for now. */
1416  if (*fn != '/')
1417  goto unsatisfied;
1418  fn[strlen(fn)-1] = '\0';
1419 
1420  /* Extract ELF Provides: from /path/to/DSO. */
1421  xx = rpmdsELF(fn, flags, rpmdsMergePRCO, PRCO);
1422  sonameP = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
1423  if (!(xx == 0 && sonameP != NULL))
1424  goto unsatisfied;
1425 
1426  /* Search using the original {EVR,"",Flags} from the dep set. */
1427  ds = rpmdsSingle(rpmdsTagN(dep), rpmdsEVR(dep), "", (evrFlags)Flags);
1428  xx = rpmdsSearch(sonameP, ds);
1429  (void)rpmdsFree(ds);
1430  ds = NULL;
1431  PRCO = rpmdsFreePRCO(PRCO);
1432 
1433  /* Was the dependency satisfied? */
1434  if (xx >= 0) {
1435  rpmdsNotify(dep, _("(soname provides)"), rc);
1436  goto exit;
1437  }
1438  goto unsatisfied;
1439  }
1440 
1441  /* Search added packages for the dependency. */
1442  if (rpmalSatisfiesDepend(ts->addedPackages, dep, NULL) != NULL) {
1443 #if defined(CACHE_DEPENDENCY_RESULT)
1444  /*
1445  * XXX Ick, context sensitive answers from dependency cache.
1446  * XXX Always resolve added dependencies within context to disambiguate.
1447  */
1448  if (_rpmds_nopromote)
1449  _cacheThisRC = 0;
1450 #endif
1451  goto exit;
1452  }
1453 
1454  /* XXX only the installer does not have the database open here. */
1455  if (rpmtsGetRdb(ts) != NULL) {
1456  /* XXX Always satisfy Requires: /, SuSE (others?) doesn't package "/" */
1457  if (Name[0] == '/' && Name[1] == '\0') {
1458  rpmdsNotify(dep, _("(root files)"), rc);
1459  goto exit;
1460  }
1461  if (Name[0] == '/') {
1462  mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, Name, 0);
1463  (void) rpmmiPrune(mi,
1464  ts->removedPackages, ts->numRemovedPackages, 1);
1465  while ((h = rpmmiNext(mi)) != NULL) {
1466  rpmdsNotify(dep, _("(db files)"), rc);
1467  mi = rpmmiFree(mi);
1468  goto exit;
1469  }
1470  mi = rpmmiFree(mi);
1471  }
1472 
1473  mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, Name, 0);
1474  (void) rpmmiPrune(mi,
1475  ts->removedPackages, ts->numRemovedPackages, 1);
1476  while ((h = rpmmiNext(mi)) != NULL) {
1477  if (rpmdsAnyMatchesDep(h, dep, _rpmds_nopromote)) {
1478  rpmdsNotify(dep, _("(db provides)"), rc);
1479  mi = rpmmiFree(mi);
1480  goto exit;
1481  }
1482  }
1483  mi = rpmmiFree(mi);
1484  }
1485 
1486  /*
1487  * Search for an unsatisfied dependency.
1488  */
1489  if (adding == 1 && retries > 0 && !(rpmtsDFlags(ts) & RPMDEPS_FLAG_NOSUGGEST)) {
1490  if (ts->solve != NULL) {
1491  xx = (*ts->solve) (ts, dep, ts->solveData);
1492  if (xx == 0)
1493  goto exit;
1494  if (xx == -1) {
1495  retries--;
1496  rpmalMakeIndex(ts->addedPackages);
1497  goto retry;
1498  }
1499  }
1500  }
1501 
1502 unsatisfied:
1503  if (Flags & RPMSENSE_MISSINGOK) {
1504  rc = 0; /* dependency is unsatisfied, but just a hint. */
1505 #if defined(CACHE_DEPENDENCY_RESULT)
1506  _cacheThisRC = 0;
1507 #endif
1508  rpmdsNotify(dep, _("(hint skipped)"), rc);
1509  } else {
1510  rc = 1; /* dependency is unsatisfied */
1511  rpmdsNotify(dep, NULL, rc);
1512  }
1513 
1514 exit:
1515  /*
1516  * If dbiOpen/dbiPut fails (e.g. permissions), we can't cache.
1517  */
1518 #if defined(CACHE_DEPENDENCY_RESULT)
1519  if (_cacheDependsRC && _cacheThisRC) {
1520  dbiIndex dbi;
1521  dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_DEPCACHE, 0);
1522  if (dbi == NULL) {
1523  _cacheDependsRC = 0;
1524  } else {
1525  const char * DNEVR;
1526  xx = 0;
1527  if ((DNEVR = rpmdsDNEVR(dep)) != NULL) {
1528  DBC * dbcursor = NULL;
1529  size_t DNEVRlen = strlen(DNEVR);
1530 
1531  xx = dbiCopen(dbi, dbiTxnid(dbi), &dbcursor, DB_WRITECURSOR);
1532 
1533  memset(key, 0, sizeof(*key));
1534 /*@i@*/ key->data = (void *) DNEVR;
1535  key->size = DNEVRlen;
1536  memset(data, 0, sizeof(*data));
1537  data->data = &rc;
1538  data->size = sizeof(rc);
1539 
1540  /*@-compmempass@*/
1541  xx = dbiPut(dbi, dbcursor, key, data, 0);
1542  /*@=compmempass@*/
1543  xx = dbiCclose(dbi, dbcursor, DB_WRITECURSOR);
1544  }
1545  if (xx)
1546  _cacheDependsRC = 0;
1547  }
1548  }
1549 #endif
1550 
1551  return rpmdsNegateRC(dep, rc);
1552 }
1553 
1567 static int checkPackageDeps(rpmts ts, const char * pkgNEVRA,
1568  /*@null@*/ rpmds requires,
1569  /*@null@*/ rpmds conflicts,
1570  /*@null@*/ rpmds dirnames,
1571  /*@null@*/ rpmds linktos,
1572  /*@null@*/ const char * depName,
1573  rpmuint32_t tscolor, int adding)
1574  /*@globals rpmGlobalMacroContext, h_errno,
1575  fileSystem, internalState @*/
1576  /*@modifies ts, requires, conflicts, dirnames, linktos,
1577  rpmGlobalMacroContext, fileSystem, internalState */
1578 {
1579  rpmps ps = rpmtsProblems(ts);
1580  rpmuint32_t dscolor;
1581  const char * Name;
1582  int terminate = 2; /* XXX terminate if rc >= terminate */
1583  int rc;
1584  int ourrc = 0;
1585 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) || defined(RPM_OPTIONAL_DIRNAME_AND_SYMLINK_DEPS) /* optional-dirname-and-symlink-deps */
1586  int dirname_deps;
1587  int symlink_deps;
1588 #endif
1589 
1590  requires = rpmdsInit(requires);
1591  if (requires != NULL)
1592  while (ourrc < terminate && rpmdsNext(requires) >= 0) {
1593 
1594  if ((Name = rpmdsN(requires)) == NULL)
1595  continue; /* XXX can't happen */
1596 
1597  /* Filter out requires that came along for the ride. */
1598  if (depName != NULL && strcmp(depName, Name))
1599  continue;
1600 
1601  /* Ignore colored requires not in our rainbow. */
1602  dscolor = rpmdsColor(requires);
1603  if (tscolor && dscolor && !(tscolor & dscolor))
1604  continue;
1605 
1606  rc = unsatisfiedDepend(ts, requires, adding);
1607 
1608  switch (rc) {
1609  case 0: /* requirements are satisfied. */
1610  /*@switchbreak@*/ break;
1611  case 1: /* requirements are not satisfied. */
1612  { fnpyKey * suggestedKeys = NULL;
1613 
1614  if (ts->availablePackages != NULL) {
1615  suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
1616  requires, NULL);
1617  }
1618 
1619  rpmdsProblem(ps, pkgNEVRA, requires, suggestedKeys, adding);
1620 
1621  }
1622  ourrc = 1;
1623  /*@switchbreak@*/ break;
1624  case 2: /* something went wrong! */
1625  default:
1626  ourrc = 2;
1627  /*@switchbreak@*/ break;
1628  }
1629  }
1630 
1631  conflicts = rpmdsInit(conflicts);
1632  if (conflicts != NULL)
1633  while (ourrc < terminate && rpmdsNext(conflicts) >= 0) {
1634 
1635  if ((Name = rpmdsN(conflicts)) == NULL)
1636  continue; /* XXX can't happen */
1637 
1638  /* Filter out conflicts that came along for the ride. */
1639  if (depName != NULL && strcmp(depName, Name))
1640  continue;
1641 
1642  /* Ignore colored conflicts not in our rainbow. */
1643  dscolor = rpmdsColor(conflicts);
1644  if (tscolor && dscolor && !(tscolor & dscolor))
1645  continue;
1646 
1647  rc = unsatisfiedDepend(ts, conflicts, adding);
1648 
1649  /* 1 == unsatisfied, 0 == satsisfied */
1650  switch (rc) {
1651  case 0: /* conflicts exist. */
1652  rpmdsProblem(ps, pkgNEVRA, conflicts, NULL, adding);
1653  ourrc = 1;
1654  /*@switchbreak@*/ break;
1655  case 1: /* conflicts don't exist. */
1656  /*@switchbreak@*/ break;
1657  case 2: /* something went wrong! */
1658  default:
1659  ourrc = 2;
1660  /*@switchbreak@*/ break;
1661  }
1662  }
1663 
1664 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) || defined(RPM_OPTIONAL_DIRNAME_AND_SYMLINK_DEPS) /* optional-dirname-and-symlink-deps */
1665  dirname_deps = rpmExpandNumeric("%{?_check_dirname_deps}%{?!_check_dirname_deps:1}");
1666  if (dirname_deps) {
1667 #endif
1668  dirnames = rpmdsInit(dirnames);
1669  if (dirnames != NULL)
1670  while (ourrc < terminate && rpmdsNext(dirnames) >= 0) {
1671 
1672  if ((Name = rpmdsN(dirnames)) == NULL)
1673  continue; /* XXX can't happen */
1674 
1675  /* Filter out dirnames that came along for the ride. */
1676  if (depName != NULL && strcmp(depName, Name))
1677  continue;
1678 
1679  /* Ignore colored dirnames not in our rainbow. */
1680  dscolor = rpmdsColor(dirnames);
1681  if (tscolor && dscolor && !(tscolor & dscolor))
1682  continue;
1683 
1684  rc = unsatisfiedDepend(ts, dirnames, adding);
1685 
1686  switch (rc) {
1687  case 0: /* requirements are satisfied. */
1688  /*@switchbreak@*/ break;
1689  case 1: /* requirements are not satisfied. */
1690  { fnpyKey * suggestedKeys = NULL;
1691 
1692  if (ts->availablePackages != NULL) {
1693  suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
1694  dirnames, NULL);
1695  }
1696 
1697  rpmdsProblem(ps, pkgNEVRA, dirnames, suggestedKeys, adding);
1698 
1699  }
1700  ourrc = 1;
1701  /*@switchbreak@*/ break;
1702  case 2: /* something went wrong! */
1703  default:
1704  ourrc = 2;
1705  /*@switchbreak@*/ break;
1706  }
1707  }
1708 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) || defined(RPM_OPTIONAL_DIRNAME_AND_SYMLINK_DEPS) /* optional-dirname-and-symlink-deps */
1709  }
1710 
1711  symlink_deps = rpmExpandNumeric("%{?_check_symlink_deps}%{?!_check_symlink_deps:1}");
1712  if (symlink_deps) {
1713 #endif
1714  linktos = rpmdsInit(linktos);
1715  if (linktos != NULL)
1716  while (ourrc < terminate && rpmdsNext(linktos) >= 0) {
1717 
1718  if ((Name = rpmdsN(linktos)) == NULL)
1719  continue; /* XXX can't happen */
1720  if (*Name == '\0') /* XXX most linktos are empty */
1721  continue;
1722 
1723  /* Filter out linktos that came along for the ride. */
1724  if (depName != NULL && strcmp(depName, Name))
1725  continue;
1726 
1727  /* Ignore colored linktos not in our rainbow. */
1728  dscolor = rpmdsColor(linktos);
1729  if (tscolor && dscolor && !(tscolor & dscolor))
1730  continue;
1731 
1732  rc = unsatisfiedDepend(ts, linktos, adding);
1733 
1734  switch (rc) {
1735  case 0: /* requirements are satisfied. */
1736  /*@switchbreak@*/ break;
1737  case 1: /* requirements are not satisfied. */
1738  { fnpyKey * suggestedKeys = NULL;
1739 
1740  if (ts->availablePackages != NULL) {
1741  suggestedKeys = rpmalAllSatisfiesDepend(ts->availablePackages,
1742  linktos, NULL);
1743  }
1744 
1745  rpmdsProblem(ps, pkgNEVRA, linktos, suggestedKeys, adding);
1746 
1747  }
1748  ourrc = 1;
1749  /*@switchbreak@*/ break;
1750  case 2: /* something went wrong! */
1751  default:
1752  ourrc = 2;
1753  /*@switchbreak@*/ break;
1754  }
1755  }
1756 #if defined(RPM_VENDOR_MANDRIVA) || defined(RPM_VENDOR_ARK) || defined(RPM_OPTIONAL_DIRNAME_AND_SYMLINK_DEPS) /* optional-dirname-and-symlink-deps */
1757  }
1758 #endif
1759 
1760  ps = rpmpsFree(ps);
1761  return ourrc;
1762 }
1763 
1774 static int checkPackageSet(rpmts ts, const char * depName,
1775  /*@only@*/ /*@null@*/ rpmmi mi, int adding)
1776  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1777  /*@modifies ts, mi, rpmGlobalMacroContext, fileSystem, internalState @*/
1778 {
1779  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
1780  rpmdepFlags depFlags = rpmtsDFlags(ts);
1781  rpmuint32_t tscolor = rpmtsColor(ts);
1782  int scareMem = 0;
1783  Header h;
1784  int terminate = 2; /* XXX terminate if rc >= terminate */
1785  int ourrc = 0;
1786 
1787  (void) rpmmiPrune(mi,
1788  ts->removedPackages, ts->numRemovedPackages, 1);
1789  while (ourrc < terminate && (h = rpmmiNext(mi)) != NULL) {
1790  rpmds requires = NULL;
1791  rpmds conflicts = NULL;
1792  rpmds dirnames = NULL;
1793  rpmds linktos = NULL;
1794  int rc;
1795 
1796  he->tag = RPMTAG_NVRA;
1797  rc = (headerGet(h, he, 0) ? 0 : 2);
1798  if (rc > ourrc)
1799  ourrc = rc;
1800  if (ourrc >= terminate) {
1801  he->p.str = _free(he->p.str);
1802  break;
1803  }
1804 
1805  if (!(depFlags & RPMDEPS_FLAG_NOREQUIRES))
1806  requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
1807  if (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS))
1808  conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
1809  if (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS))
1810  dirnames = rpmdsNew(h, RPMTAG_DIRNAMES, scareMem);
1811  if (!(depFlags & RPMDEPS_FLAG_NOLINKTOS))
1812  linktos = rpmdsNew(h, RPMTAG_FILELINKTOS, scareMem);
1813 
1814  (void) rpmdsSetNoPromote(requires, _rpmds_nopromote);
1815  (void) rpmdsSetNoPromote(conflicts, _rpmds_nopromote);
1816  (void) rpmdsSetNoPromote(dirnames, _rpmds_nopromote);
1817  (void) rpmdsSetNoPromote(linktos, _rpmds_nopromote);
1818 
1819  rc = checkPackageDeps(ts, he->p.str,
1820  requires, conflicts, dirnames, linktos,
1821  depName, tscolor, adding);
1822 
1823  (void)rpmdsFree(linktos);
1824  linktos = NULL;
1825  (void)rpmdsFree(dirnames);
1826  dirnames = NULL;
1827  (void)rpmdsFree(conflicts);
1828  conflicts = NULL;
1829  (void)rpmdsFree(requires);
1830  requires = NULL;
1831  he->p.str = _free(he->p.str);
1832 
1833  if (rc > ourrc)
1834  ourrc = rc;
1835  }
1836  mi = rpmmiFree(mi);
1837 
1838  return ourrc;
1839 }
1840 
1847 static int checkDependentPackages(rpmts ts, const char * depName)
1848  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1849  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
1850 {
1851  int rc = 0;
1852 
1853  /* XXX rpmdb can be closed here, avoid error msg. */
1854  if (rpmtsGetRdb(ts) != NULL) {
1855  rpmmi mi;
1856  mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, depName, 0);
1857  rc = checkPackageSet(ts, depName, mi, 0);
1858  }
1859  return rc;
1860 }
1861 
1868 static int checkDependentConflicts(rpmts ts, const char * depName)
1869  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1870  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
1871 {
1872  int rc = 0;
1873 
1874  /* XXX rpmdb can be closed here, avoid error msg. */
1875  if (rpmtsGetRdb(ts) != NULL) {
1876  rpmmi mi;
1877  mi = rpmtsInitIterator(ts, RPMTAG_CONFLICTNAME, depName, 0);
1878  rc = checkPackageSet(ts, depName, mi, 1);
1879  }
1880 
1881  return rc;
1882 }
1883 
1885 {
1886  const char * depName = NULL;
1887  rpmdepFlags depFlags = rpmtsDFlags(ts);
1888  rpmuint32_t tscolor = rpmtsColor(ts);
1889  rpmmi mi = NULL;
1890  rpmtsi pi = NULL; rpmte p;
1891  int closeatexit = 0;
1892  int xx;
1893  int terminate = 2; /* XXX terminate if rc >= terminate */
1894  int rc = 0;
1895  int ourrc = 0;
1896 
1897 if (_rpmts_debug)
1898 fprintf(stderr, "--> %s(%p) tsFlags 0x%x\n", __FUNCTION__, ts, rpmtsFlags(ts));
1899 
1900  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
1901 
1902  /* Do lazy, readonly, open of rpm database. */
1903  if (rpmtsGetRdb(ts) == NULL && rpmtsDBMode(ts) != -1) {
1904  rc = (rpmtsOpenDB(ts, rpmtsDBMode(ts)) ? 2 : 0);
1905  closeatexit = (rc == 0);
1906  }
1907  if (rc && (ourrc = rc) >= terminate)
1908  goto exit;
1909 
1910  ts->probs = rpmpsFree(ts->probs);
1911 
1912  rpmalMakeIndex(ts->addedPackages);
1913 
1914  /*
1915  * Look at all of the added packages and make sure their dependencies
1916  * are satisfied.
1917  */
1918  pi = rpmtsiInit(ts);
1919  while (ourrc < terminate && (p = rpmtsiNext(pi, TR_ADDED)) != NULL) {
1920  rpmds provides, requires, conflicts, dirnames, linktos;
1921  rpmfi fi;
1922 
1923 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */
1924  rpmlog(RPMLOG_DEBUG, "========== +++ %s %s/%s 0x%x\n",
1925  rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1926 /*@=nullpass@*/
1927  requires = (!(depFlags & RPMDEPS_FLAG_NOREQUIRES)
1928  ? rpmteDS(p, RPMTAG_REQUIRENAME) : NULL);
1929  conflicts = (!(depFlags & RPMDEPS_FLAG_NOCONFLICTS)
1930  ? rpmteDS(p, RPMTAG_CONFLICTNAME) : NULL);
1931  /* XXX srpm's don't have directory paths. */
1932  if (p->isSource) {
1933  dirnames = NULL;
1934  linktos = NULL;
1935  } else {
1936  dirnames = (!(depFlags & RPMDEPS_FLAG_NOPARENTDIRS)
1937  ? rpmteDS(p, RPMTAG_DIRNAMES) : NULL);
1938  linktos = (!(depFlags & RPMDEPS_FLAG_NOLINKTOS)
1939  ? rpmteDS(p, RPMTAG_FILELINKTOS) : NULL);
1940  }
1941 
1942  rc = checkPackageDeps(ts, rpmteNEVRA(p),
1943  requires, conflicts, dirnames, linktos,
1944  NULL, tscolor, 1);
1945  if (rc && (ourrc = rc) >= terminate)
1946  break;
1947 
1948  provides = rpmteDS(p, RPMTAG_PROVIDENAME);
1949  provides = rpmdsInit(provides);
1950  if (provides != NULL)
1951  while (ourrc < terminate && rpmdsNext(provides) >= 0) {
1952  depName = _free(depName);
1953  depName = xstrdup(rpmdsN(provides));
1954 
1955 #ifdef NOTYET
1956  if (rpmdsNSType(provides) == RPMNS_TYPE_ENVVAR) {
1957  const char * EVR = rpmdsEVR(provides);
1958  if (rpmdsNegateRC(provides, 0))
1959  EVR = NULL;
1960  if (envPut(depName, EVR));
1961  rc = 2;
1962  } else
1963 #endif
1964 
1965  /* Adding: check provides key against conflicts matches. */
1966  if (checkDependentConflicts(ts, depName))
1967  rc = 1;
1968  }
1969  if (rc && (ourrc = rc) >= terminate)
1970  break;
1971 
1972  fi = rpmteFI(p, RPMTAG_BASENAMES);
1973  fi = rpmfiInit(fi, 0);
1974  while (ourrc < terminate && rpmfiNext(fi) >= 0) {
1975  depName = _free(depName);
1976  depName = xstrdup(rpmfiFN(fi));
1977  /* Adding: check filename against conflicts matches. */
1978  if (checkDependentConflicts(ts, depName))
1979  rc = 1;
1980  }
1981  if (rc && (ourrc = rc) >= terminate)
1982  break;
1983  }
1984  pi = rpmtsiFree(pi);
1985  if (rc && (ourrc = rc) >= terminate)
1986  goto exit;
1987 
1988  /*
1989  * Look at the removed packages and make sure they aren't critical.
1990  */
1991  pi = rpmtsiInit(ts);
1992  while (ourrc < terminate && (p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
1993  rpmds provides;
1994  rpmfi fi;
1995 
1996 /*@-nullpass@*/ /* FIX: rpmts{A,O} can return null. */
1997  rpmlog(RPMLOG_DEBUG, "========== --- %s %s/%s 0x%x\n",
1998  rpmteNEVR(p), rpmteA(p), rpmteO(p), rpmteColor(p));
1999 /*@=nullpass@*/
2000 
2001  provides = rpmteDS(p, RPMTAG_PROVIDENAME);
2002  provides = rpmdsInit(provides);
2003  if (provides != NULL)
2004  while (ourrc < terminate && rpmdsNext(provides) >= 0) {
2005  depName = _free(depName);
2006  depName = xstrdup(rpmdsN(provides));
2007 
2008  /* Erasing: check provides against requiredby matches. */
2009  if (checkDependentPackages(ts, depName))
2010  rc = 1;
2011  }
2012  if (rc && (ourrc = rc) >= terminate)
2013  break;
2014 
2015  fi = rpmteFI(p, RPMTAG_BASENAMES);
2016  fi = rpmfiInit(fi, 0);
2017  while (ourrc < terminate && rpmfiNext(fi) >= 0) {
2018  depName = _free(depName);
2019  depName = xstrdup(rpmfiFN(fi));
2020  /* Erasing: check filename against requiredby matches. */
2021  if (checkDependentPackages(ts, depName))
2022  rc = 1;
2023  }
2024  if (rc && (ourrc = rc) >= terminate)
2025  break;
2026  }
2027  pi = rpmtsiFree(pi);
2028  if (rc && (ourrc = rc) >= terminate)
2029  goto exit;
2030 
2031  /*
2032  * Make sure transaction dependencies are satisfied.
2033  */
2034  { const char * tsNEVRA = "transaction dependencies";
2037  rpmds D = NULL;
2038  rpmds L = NULL;
2039  const char * dep = NULL;
2040  int adding = 2;
2041  tscolor = 0; /* XXX no coloring for transaction dependencies. */
2042  rc = checkPackageDeps(ts, tsNEVRA, R, C, D, L, dep, tscolor, adding);
2043  }
2044  if (rc && (ourrc = rc) >= terminate)
2045  goto exit;
2046 
2047 exit:
2048  mi = rpmmiFree(mi);
2049  pi = rpmtsiFree(pi);
2050  depName = _free(depName);
2051 
2052  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0);
2053 
2054  if (closeatexit)
2055  xx = rpmtsCloseDB(ts);
2056 #if defined(CACHE_DEPENDENCY_RESULT)
2057  else if (_cacheDependsRC)
2059 #endif
2060 
2061 #ifdef NOTYET
2062  /* On failed dependencies, perform the autorollback goal (if any). */
2063  { rpmps ps = rpmtsProblems(ts);
2064  if (rc || rpmpsNumProblems(ps) > 0)
2065  (void) rpmtsRollback(ts, RPMPROB_FILTER_NONE, 0, NULL);
2066  ps = rpmpsFree(ps);
2067  }
2068 #endif
2069 
2070  return ourrc;
2071 }
2072 
2073 int (*rpmtsCheck) (rpmts ts)
2074  = _rpmtsCheck;