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