rpm  5.4.15
rpminstall.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmiotypes.h>
9 #include <poptIO.h>
10 
11 #include <rpmtag.h>
12 #define _RPMEVR_INTERNAL /* XXX expose rpmVersionCompare prototype */
13 #include <rpmevr.h>
14 #include "rpmdb.h"
15 #ifdef NOTYET
16 #include "rpmds.h" /* XXX ts->suggests, +foo -foo =foo args */
17 #endif
18 
19 #include "rpmte.h" /* XXX rpmtsPrint() */
20 #define _RPMTS_INTERNAL /* XXX ts->suggests */
21 #include <rpmts.h>
22 
23 #include "manifest.h"
24 #define _RPMGI_INTERNAL /* XXX "+bing" args need gi->h. */
25 #include "rpmgi.h"
26 
27 #include <rpmlib.h>
28 
29 #include <rpmcli.h>
30 #define _RPMROLLBACK_INTERNAL
31 #include <rpmrollback.h>
32 
33 #include "debug.h"
34 
35 /*@access FD_t @*/ /* XXX void * arg */
36 /*@access rpmts @*/ /* XXX ts->suggests */
37 /*@access rpmgi @*/ /* XXX gi->h */
38 /*@access fnpyKey @*/ /* XXX cast */
39 
40 #ifdef __cplusplus
41 
42 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
43 
44 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
45 #define VSF_SET(_vsflags, _FLAG) \
46  (*((unsigned *)&(_vsflags)) |= (RPMVSF_##_FLAG))
47 #define VSF_CLR(_vsflags, _FLAG) \
48  (*((unsigned *)&(_vsflags)) &= ~(RPMVSF_##_FLAG))
49 
50 GENfree(const void **)
51 
52 #else /* __cplusplus */
53 
54 #define QVA_ISSET(_qvaflags, _FLAG) ((_qvaflags) & (VERIFY_##_FLAG))
55 
56 #define VSF_ISSET(_vsflags, _FLAG) ((_vsflags) & (RPMVSF_##_FLAG))
57 #define VSF_SET(_vsflags, _FLAG) (_vsflags) |= (RPMVSF_##_FLAG)
58 #define VSF_CLR(_vsflags, _FLAG) (_vsflags) &= ~(RPMVSF_##_FLAG)
59 
60 #endif /* __cplusplus */
61 
62 /*@unchecked@*/
64 /*@unchecked@*/
66 /*@unchecked@*/
68 /*@unchecked@*/
70 /*@unchecked@*/
72 
79 static void printHash(const rpmuint64_t amount, const rpmuint64_t total)
80  /*@globals rpmcliHashesCurrent, rpmcliHashesTotal,
81  rpmcliProgressCurrent, fileSystem @*/
82  /*@modifies rpmcliHashesCurrent, rpmcliHashesTotal,
83  rpmcliProgressCurrent, fileSystem @*/
84 {
85  int hashesNeeded;
86 
87  rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
88 
89  if (rpmcliHashesCurrent != rpmcliHashesTotal) {
90  float pct = (float) (total ? (((float) amount) / total) : 1);
91  hashesNeeded = (int)((rpmcliHashesTotal * pct) + 0.5);
92  while (hashesNeeded > rpmcliHashesCurrent) {
93  if (isatty (STDOUT_FILENO)) {
94  int i;
95  for (i = 0; i < rpmcliHashesCurrent; i++)
96  (void) putchar ('#');
97  for (; i < rpmcliHashesTotal; i++)
98  (void) putchar (' ');
99  fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
100  for (i = 0; i < (rpmcliHashesTotal + 6); i++)
101  (void) putchar ('\b');
102  } else
103  fprintf(stdout, "#");
104 
105  rpmcliHashesCurrent++;
106  }
107  (void) fflush(stdout);
108 
109  if (rpmcliHashesCurrent == rpmcliHashesTotal) {
110  int i;
111  rpmcliProgressCurrent++;
112  if (isatty(STDOUT_FILENO)) {
113  for (i = 1; i < rpmcliHashesCurrent; i++)
114  (void) putchar ('#');
115  pct = (float) (rpmcliProgressTotal
116  ? (((float) rpmcliProgressCurrent) / rpmcliProgressTotal)
117  : 1);
118  fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
119  }
120  fprintf(stdout, "\n");
121  }
122  (void) fflush(stdout);
123  }
124 }
125 
126 void * rpmShowProgress(/*@null@*/ const void * arg,
127  const rpmCallbackType what,
128  const rpmuint64_t amount,
129  const rpmuint64_t total,
130  /*@null@*/ fnpyKey key,
131  /*@null@*/ void * data)
132  /*@globals rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
133  rpmGlobalMacroContext, fileSystem @*/
134  /*@modifies rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
135  rpmGlobalMacroContext, fileSystem @*/
136 {
137 /*@-abstract -castexpose @*/
138  Header h = (Header) arg;
139 /*@=abstract =castexpose @*/
140  const char * s;
141  int flags = (int) ((long)data);
142  void * rc = NULL;
143 /*@-abstract -assignexpose @*/
144  const char * filename = (const char *)key;
145 /*@=abstract =assignexpose @*/
146  static FD_t fd = NULL;
147  int xx;
148 
149  switch (what) {
151  if (filename == NULL || filename[0] == '\0')
152  return NULL;
153  fd = Fopen(filename, "r%{?_rpmgio}");
154 
155  /* XXX Retry once to handle http:// server timeout reopen's. */
156  if (Ferror(fd)) {
157  int ut = urlPath(filename, NULL);
158  if (ut == URL_IS_HTTP || ut == URL_IS_HTTPS) {
159  /* XXX HACK: Fclose(fd) no workie here. */
160  fd = Fopen(filename, "r%{?_rpmgio}");
161  }
162  }
163 
164  if (fd == NULL || Ferror(fd)) {
165  rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), filename,
166  Fstrerror(fd));
167  if (fd != NULL) {
168  xx = Fclose(fd);
169  fd = NULL;
170  }
171  } else {
172  long oldfl;
173  fd = fdLink(fd, "persist (showProgress)");
174  oldfl=Fcntl(fd, F_GETFD, 0);
175  if(oldfl >= 0) {
176  oldfl |= FD_CLOEXEC; /* scripts shouldn't inherit rpm file descriptor */
177  Fcntl(fd, F_SETFD, (void*)oldfl);
178  }
179  }
180 
181 #if defined(POSIX_FADV_WILLNEED)
182  (void) Fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
183 #endif
184 
185 /*@+voidabstract@*/
186  return (void *)fd;
187 /*@=voidabstract@*/
188  /*@notreached@*/ break;
189 
191  /*@-type@*/ /* FIX: still necessary? */
192  fd = fdFree(fd, "persist (showProgress)");
193  /*@=type@*/
194  if (fd != NULL) {
195  xx = Fclose(fd);
196  fd = NULL;
197  }
198  break;
199 
201  rpmcliHashesCurrent = 0;
202  if (h == NULL || !(flags & INSTALL_LABEL))
203  break;
204  /* @todo Remove headerSprintf() on a progress callback. */
205  if (flags & INSTALL_HASH) {
206  s = headerSprintf(h, "%{NAME}",
207  NULL, rpmHeaderFormats, NULL);
208  if (isatty (STDOUT_FILENO))
209  fprintf(stdout, "%4d:%-23.23s", (int)rpmcliProgressCurrent + 1, s);
210  else
211  fprintf(stdout, "%-28.28s", s);
212  (void) fflush(stdout);
213  s = _free(s);
214  } else {
215  char * t = rpmExpand("%{?___NVRA}%{!?___NVRA:%%{NAME}-%%{VERSION}-%%{RELEASE}}", NULL);
216  s = headerSprintf(h, t, NULL, rpmHeaderFormats, NULL);
217  fprintf(stdout, "%s\n", s);
218  (void) fflush(stdout);
219  s = _free(s);
220  t = _free(t);
221  }
222  break;
223 
226 /*@+relaxtypes@*/
227  if (flags & INSTALL_PERCENT)
228  fprintf(stdout, "%%%% %f\n", (double) (total
229  ? ((((float) amount) / total) * 100)
230  : 100.0));
231  else if (flags & INSTALL_HASH)
232  printHash(amount, total);
233 /*@=relaxtypes@*/
234  (void) fflush(stdout);
235  break;
236 
238  rpmcliHashesCurrent = 0;
239  rpmcliProgressTotal = 1;
240  rpmcliProgressCurrent = 0;
241  if (!(flags & INSTALL_LABEL))
242  break;
243  if (flags & INSTALL_HASH)
244  fprintf(stdout, "%-28s", _("Preparing..."));
245  else
246  fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
247  (void) fflush(stdout);
248  break;
249 
251  if (flags & INSTALL_HASH)
252  printHash(1, 1); /* Fixes "preparing..." progress bar */
253  rpmcliProgressTotal = rpmcliPackagesTotal;
254  rpmcliProgressCurrent = 0;
255  break;
256 
258  rpmcliHashesCurrent = 0;
259  rpmcliProgressTotal = total;
260  rpmcliProgressCurrent = 0;
261  if (!(flags & INSTALL_LABEL))
262  break;
263  if (flags & INSTALL_HASH)
264  fprintf(stdout, "%-28s\n", _("Repackaging..."));
265  else
266  fprintf(stdout, "%s\n", _("Repackaging erased files..."));
267  (void) fflush(stdout);
268  break;
269 
271  if (amount && (flags & INSTALL_HASH))
272  printHash(1, 1); /* Fixes "preparing..." progress bar */
273  break;
274 
276  rpmcliProgressTotal = total;
277  rpmcliProgressCurrent = total;
278  if (flags & INSTALL_HASH)
279  printHash(1, 1); /* Fixes "preparing..." progress bar */
280  rpmcliProgressTotal = rpmcliPackagesTotal;
281  rpmcliProgressCurrent = 0;
282  if (!(flags & INSTALL_LABEL))
283  break;
284  if (flags & INSTALL_HASH)
285  fprintf(stdout, "%-28s\n", _("Upgrading..."));
286  else
287  fprintf(stdout, "%s\n", _("Upgrading packages..."));
288  (void) fflush(stdout);
289  break;
290 
292  break;
294  break;
296  break;
298  break;
300  break;
302  break;
303  case RPMCALLBACK_UNKNOWN:
304  default:
305  break;
306  }
307 
308  return rc;
309 }
310 
311 int rpmcliInstallProblems(rpmts ts, const char * msg, int rc)
312  /*@globals fileSystem @*/
313  /*@modifies ts, fileSystem @*/
314 {
315  rpmps ps = rpmtsProblems(ts);
316 
317  if (rc && rpmpsNumProblems(ps) > 0) {
318  if (msg)
319  rpmlog(RPMLOG_ERR, "%s:\n", msg);
320  rpmpsPrint(NULL, ps);
321  }
322  ps = rpmpsFree(ps);
323  return rc;
324 }
325 
327 {
328  if (ts->suggests != NULL && ts->nsuggests > 0) {
329  const char * s;
330  int i;
331 
332  rpmlog(RPMLOG_NOTICE, _(" Suggested resolutions:\n"));
333  for (i = 0; i < ts->nsuggests && (s = (char *)ts->suggests[i]) != NULL;
334  s = _free(s), ts->suggests[i++] = NULL)
335  {
336  rpmlog(RPMLOG_NOTICE, "\t%s\n", s);
337  }
338  ts->suggests = _free(ts->suggests);
339  }
340  return 0;
341 }
342 
344 {
345 /*@-evalorder@*/
346  return rpmcliInstallProblems(ts, _("Failed dependencies"), rpmtsCheck(ts));
347 /*@=evalorder@*/
348 }
349 
351 {
352 /*@-evalorder@*/
353  return rpmcliInstallProblems(ts, _("Ordering problems"), rpmtsOrder(ts));
354 /*@=evalorder@*/
355 }
356 
358 {
359 /*@-evalorder@*/
360  return rpmcliInstallProblems(ts, _("Install/Erase problems"),
361  rpmtsRun(ts, okProbs, ignoreSet));
362 /*@=evalorder@*/
363 }
364 
365 static rpmRC rpmcliEraseElement(rpmts ts, const char * arg)
366  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
367  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
368 {
369  rpmmi mi;
370  Header h;
371  rpmRC rc = RPMRC_OK;
372  int xx;
373 
374  mi = rpmtsInitIterator(ts, RPMTAG_NVRA, arg, 0);
375  if (mi == NULL)
376  return RPMRC_NOTFOUND;
377 
378  while ((h = rpmmiNext(mi)) != NULL) {
379  uint32_t hdrNum = rpmmiInstance(mi);
380 
381  if (hdrNum == 0) { /* XXX can't happen. */
382  rc = RPMRC_FAIL;
383  break;
384  }
385  xx = rpmtsAddEraseElement(ts, h, hdrNum);
386  }
387  mi = rpmmiFree(mi);
388 
389  /* XXX FIXME: return rc? */
390  return (rpmRC)0;
391 }
392 
393 static const char * rpmcliWalkFirst(ARGV_t av, miRE mire)
394  /*@globals fileSystem, internalState @*/
395  /*@modifies mire, fileSystem, internalState @*/
396 {
397  /* XXX use global ftsOpts? */
398  /* XXX changing FTS_LOGICAL to FTS_PHYSICAL prevents symlink follow. */
399  /* XXX FTS_NOCHDIR is automatically assumed for URI's */
400  int _ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
401  FTS * ftsp = NULL;
402  FTSENT * fts;
403  const char * fn = NULL;
404  int fts_level = 1;
405  int xx;
406 
407  if (av != NULL && av[0] != NULL)
408  ftsp = Fts_open((char *const *)av, _ftsOpts, NULL);
409  if (ftsp != NULL)
410  while((fts = Fts_read(ftsp)) != NULL) {
411  switch (fts->fts_info) {
412  /* No-op conditions. */
413  case FTS_D: /* preorder directory */
414  case FTS_DP: /* postorder directory */
415  /* XXX Don't recurse downwards, all elements should be files. */
416  if (fts_level > 0 && fts->fts_level >= fts_level)
417  xx = Fts_set(ftsp, fts, FTS_SKIP);
418  /*@fallthrough@*/
419  case FTS_DOT: /* dot or dot-dot */
420  continue;
421  /*@notreached@*/ /*@switchbreak@*/ break;
422  case FTS_F: /* regular file */
423  if (mireRegexec(mire, fts->fts_accpath, 0) < 0)
424  continue;
425  /*@switchbreak@*/ break;
426  /* Error conditions. */
427  case FTS_NS: /* stat(2) failed */
428  case FTS_DNR: /* unreadable directory */
429  case FTS_ERR: /* error; errno is set */
430  case FTS_DC: /* directory that causes cycles */
431  case FTS_DEFAULT: /* none of the above */
432  case FTS_INIT: /* initialized only */
433  case FTS_NSOK: /* no stat(2) requested */
434  case FTS_SL: /* symbolic link */
435  case FTS_SLNONE: /* symbolic link without target */
436  case FTS_W: /* whiteout object */
437  default:
438  goto exit;
439  /*@notreached@*/ /*@switchbreak@*/ break;
440  }
441 
442  /* Stop on first file that matches. */
443  fn = xstrdup(fts->fts_accpath);
444  break;
445  }
446 
447 exit:
448  xx = Fts_close(ftsp);
449  return fn;
450 }
451 
452 static const char * rpmcliInstallElementPath(/*@unused@*/ rpmts ts,
453  const char * arg)
454  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
455  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
456 {
457  /* A glob pattern list to match repository directories. */
458  const char * fn = rpmExpand(
459  "%{?_rpmgi_pattern_glob}"
460  "%{!?_rpmgi_pattern_glob:.}",
461  NULL
462  );
463  /* A regex pattern list to match candidate *.rpm files. */
464  const char * mirePattern = rpmExpand(
465  "%{?_rpmgi_pattern_regex:%{_rpmgi_pattern_regex ", arg, "}}"
466  "%{!?_rpmgi_pattern_regex:", arg, "-[^-]+-[^-]+\\.[^.]+\\.rpm$}",
467  NULL
468  );
469  miRE mire = mireNew(RPMMIRE_REGEX, 0);
470  ARGV_t dav = NULL;
471  int dac = 0;
472  ARGV_t av = NULL;
473  int xx = mireRegcomp(mire, mirePattern);
474  int i;
475 
476  /* Get list of candidate repository patterns. */
477  xx = argvSplit(&dav, fn, ":");
478  fn = _free(fn);
479  if (xx || dav == NULL)
480  goto exit;
481 
482  dac = argvCount(dav);
483  for (i = 0; i < dac; i++) {
484  ARGV_t nav = NULL;
485  int nac = 0;
486 
487  /* Make sure only directory paths are matched. */
488  fn = rpmGetPath(dav[i], "/", NULL);
489  xx = rpmGlob(fn, &nac, &nav);
490 
491  if (nav != NULL)
492  for (i = 0; i < nac; i++) {
493  const char * t = nav[i];
494  size_t nt = strlen(t);
495 
496  /* Make sure that final directory paths have trailing '/' */
497  if (!(nt > 0 && t[nt-1] == '/'))
498  continue;
499 
500  t = rpmExpand(t, "/", NULL);
501  nav[i] = _free(nav[i]);
502  nav[i] = t;
503  }
504 
505  /* Append matches to list of repository directories. */
506  if (nac > 0 && nav != NULL)
507  xx = argvAppend(&av, nav);
508  nav = argvFree(nav);
509  nac = 0;
510  fn = _free(fn);
511  }
512 
513  /* Walk (possibly multi-root'd) directories, until 1st match is found. */
514  fn = rpmcliWalkFirst(av, mire);
515 
516 exit:
517  av = argvFree(av);
518  dav = argvFree(dav);
519  mire = mireFree(mire);
520  mirePattern = _free(mirePattern);
521 
522  return fn;
523 }
524 
525 /*@-redef@*/ /* XXX Add rpmfi methods to make rpmRelocation opaque. */
526 struct rpmRelocation_s {
527 /*@only@*/ /*@null@*/
528  const char * oldPath;
529 /*@only@*/ /*@null@*/
530  const char * newPath;
531 };
532 /*@=redef@*/
533 
535 int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv)
536 {
537  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
538  ARGV_t avfn = NULL;
539  int acfn = 0;
540  int numFailed = 0;
541  int numRPMS = 0;
542  rpmRelocation relocations = NULL;
543  rpmVSFlags vsflags, ovsflags;
544  rpmRC rpmrc;
545  int rc;
546  int xx;
547 
548  if (argv == NULL) goto exit;
549 
550  (void) rpmtsSetGoal(ts, TSM_INSTALL);
551  rpmcliPackagesTotal = 0;
552 
553  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
554  ia->transFlags = (rpmtransFlags)
556 
557  (void) rpmtsSetFlags(ts, ia->transFlags);
558  (void) rpmtsSetDFlags(ts, ia->depFlags);
559 
560  /* Display and set autorollback goal. */
561  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
562  if (ia->arbtid) {
563  time_t ttid = (time_t)ia->arbtid;
564  rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
565  ctime(&ttid), ia->arbtid);
566  rpmtsSetARBGoal(ts, ia->arbtid);
567  }
568  }
569 
571  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_erase}");
572  else
573  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_install}");
574  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
575 #if defined(SUPPORT_NOSIGNATURES)
576  if (!QVA_ISSET(ia->qva_flags, DIGEST)) {
577  VSF_SET(vsflags, NOSHA1HEADER);
578  VSF_SET(vsflags, NOMD5HEADER);
579  VSF_SET(vsflags, NOSHA1);
580  VSF_SET(vsflags, NOMD5);
581  }
582  if (!QVA_ISSET(ia->qva_flags, SIGNATURE)) {
583  VSF_SET(vsflags, NODSAHEADER);
584  VSF_SET(vsflags, NORSAHEADER);
585  VSF_SET(vsflags, NODSA);
586  VSF_SET(vsflags, NORSA);
587  }
588  if (!QVA_ISSET(ia->qva_flags, HDRCHK)) {
589  VSF_SET(vsflags, NOHDRCHK);
590  }
591  VSF_SET(vsflags, NEEDPAYLOAD);
592 #endif
593  ovsflags = rpmtsSetVSFlags(ts, vsflags);
594 
595  { int notifyFlags;
596  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
597  xx = rpmtsSetNotifyCallback(ts,
598  rpmShowProgress, (void *) ((long)notifyFlags));
599  }
600 
601  if ((relocations = ia->relocations) != NULL) {
602  while (relocations->oldPath)
603  relocations++;
604  if (relocations->newPath == NULL)
605  relocations = NULL;
606  }
607 
608  { /* start-of-transaction-build */
609  int tag = (ia->qva_source == RPMQV_FTSWALK)
611  rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
612  rpmgiFlags _giFlags = RPMGI_NONE;
613  const char * fn = NULL;;
614 
615 /*@-mods@*/
616  if (rpmioFtsOpts == 0)
618 /*@=mods@*/
619  rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, _giFlags);
620  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
621  Header h;
622 
623  fn = _free(fn);
624  fn = xstrdup(rpmgiHdrPath(gi));
625 
626  /* === Check for "+bing" lookaside paths within install transaction. */
627  if (fn[0] == '+') {
628  const char * nfn;
629  addMacro(NULL, "NEVRA", NULL, &fn[1], RMIL_GLOBAL);
630  nfn = rpmcliInstallElementPath(ts, &fn[1]);
631  delMacro(NULL, "NEVRA");
632  if (nfn == NULL) {
633  rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be found\n"), fn);
634  numFailed++; /* XXX multiple erasures? */
635  continue;
636  }
637  fn = _free(fn);
638  fn = nfn;
639  /* XXX hack into rpmgi innards for now ... */
640  h = rpmgiReadHeader(gi, fn);
641  if (h != NULL)
642  gi->h = headerLink(h);
643  (void)headerFree(h);
644  h = NULL;
645  }
646 
647  /* === Check for "-bang" erasures within install transaction. */
648  if (fn[0] == '-') {
649  switch (rpmcliEraseElement(ts, &fn[1])) {
650  case RPMRC_OK:
651  numRPMS++; /* XXX multiple erasures? */
652  /*@switchbreak@*/ break;
653  case RPMRC_NOTFOUND:
654  default:
655  rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be erased\n"), fn);
656  numFailed++; /* XXX multiple erasures? */
657  fn = _free(fn); /* XXX coverity #1035884 */
658  goto exit;
659  /*@notreached@*/ /*@switchbreak@*/ break;
660  }
661  continue;
662  }
663 
664  h = rpmgiHeader(gi);
665  if (h == NULL) {
666  numFailed++;
667  continue;
668  }
669 
670  /* === Check for relocatable package. */
671  if (relocations) {
672  he->tag = RPMTAG_PREFIXES;
673  xx = headerGet(h, he, 0);
674  if (xx && he->c == 1) {
675  relocations->oldPath = xstrdup(he->p.argv[0]);
676  he->p.ptr = _free(he->p.ptr);
677  } else {
678  he->p.ptr = _free(he->p.ptr);
679  he->tag = RPMTAG_NVRA;
680  xx = headerGet(h, he, 0);
682  _("package %s is not relocatable\n"), he->p.str);
683  he->p.ptr = _free(he->p.ptr);
684  numFailed++;
685  fn = _free(fn); /* XXX coverity #1035884 */
686  goto exit;
687  /*@notreached@*/
688  }
689  }
690 
691  /* === On --freshen, verify package is installed and newer. */
693  rpmmi mi;
694  Header oldH;
695  int count;
696 
697  he->tag = RPMTAG_NAME;
698  xx = headerGet(h, he, 0);
699 assert(xx != 0 && he->p.str != NULL);
700  mi = rpmtsInitIterator(ts, RPMTAG_NAME, he->p.str, 0);
701  he->p.ptr = _free(he->p.ptr);
702  count = rpmmiCount(mi);
703  while ((oldH = rpmmiNext(mi)) != NULL) {
704  if (rpmVersionCompare(oldH, h) < 0)
705  /*@innercontinue@*/ continue;
706  /* same or newer package already installed */
707  count = 0;
708  /*@innerbreak@*/ break;
709  }
710  mi = rpmmiFree(mi);
711  if (count == 0)
712  continue;
713  /* Package is newer than those currently installed. */
714  }
715 
716  /* === Add binary package to transaction set. */
717  xx = argvAdd(&avfn, fn);
718  rc = rpmtsAddInstallElement(ts, h, (fnpyKey)avfn[acfn++],
720  ia->relocations);
721 
722  if (relocations)
723  relocations->oldPath = _free(relocations->oldPath);
724 
725  numRPMS++;
726  }
727 
728  /* XXX disambiguate end-of-iteration from item failures. */
729  if (rpmrc == RPMRC_NOTFOUND)
730  rpmrc = (rpmRC) rpmgiRc(gi);
731 
732  fn = _free(fn);
733  gi = rpmgiFree(gi);
734 
735  } /* end-of-transaction-build */
736 
737  /* XXX exit if the iteration failed. */
738  if (rpmrc != RPMRC_OK)
739  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
740  if (numFailed) goto exit;
741 
742  if (numRPMS) {
744  && (rc = rpmcliInstallCheck(ts)) != 0) {
745  numFailed = numRPMS;
746  (void) rpmcliInstallSuggests(ts);
747  }
748 
750  && (rc = rpmcliInstallOrder(ts)) != 0)
751  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
752 
753  /* Drop added/available package indices and dependency sets. */
754  rpmtsClean(ts);
755 
756  /* XXX Avoid empty transaction msg, run iff there are elements. */
757  if (numFailed == 0 && rpmtsNElements(ts) > 0
758  && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter)) != 0) {
759  if (rc > 0)
760  numFailed = rc;
761  else
762  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
763  }
764  }
765 
766  if (numFailed) goto exit;
767 
768 exit:
769  avfn = argvFree(avfn);
770 
771 #ifdef NOTYET /* XXX grrr, segfault in selabel_close */
773  matchpathcon_fini();
774 #endif
775 
776  rpmtsEmpty(ts);
777 
778  return numFailed;
779 }
780 
781 int rpmErase(rpmts ts, QVA_t ia, const char ** argv)
782 {
783  const char ** arg;
784  int numFailed = 0;
785  int numRPMS = 0;
786  rpmVSFlags vsflags, ovsflags;
787  int rc;
788 
789  if (argv == NULL) return 0;
790 
791  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_erase}");
792  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
793 #if defined(SUPPORT_NOSIGNATURES)
794  if (!QVA_ISSET(ia->qva_flags, DIGEST)) {
795  VSF_SET(vsflags, NOSHA1HEADER);
796  VSF_SET(vsflags, NOMD5HEADER);
797  VSF_SET(vsflags, NOSHA1);
798  VSF_SET(vsflags, NOMD5);
799  }
800  if (!QVA_ISSET(ia->qva_flags, SIGNATURE)) {
801  VSF_SET(vsflags, NODSAHEADER);
802  VSF_SET(vsflags, NORSAHEADER);
803  VSF_SET(vsflags, NODSA);
804  VSF_SET(vsflags, NORSA);
805  }
806  if (!QVA_ISSET(ia->qva_flags, HDRCHK)) {
807  VSF_SET(vsflags, NOHDRCHK);
808  }
809  VSF_CLR(vsflags, NEEDPAYLOAD); /* XXX needed? */
810 #endif
811  ovsflags = rpmtsSetVSFlags(ts, vsflags);
812 
813  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
814  ia->transFlags = (rpmtransFlags)
816 
817  (void) rpmtsSetFlags(ts, ia->transFlags);
818  (void) rpmtsSetDFlags(ts, ia->depFlags);
819 
820  /* Display and set autorollback goal. */
821  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
822  if (ia->arbtid) {
823  time_t ttid = (time_t)ia->arbtid;
824  rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
825  ctime(&ttid), ia->arbtid);
826  rpmtsSetARBGoal(ts, ia->arbtid);
827  }
828  }
829 
830 #ifdef NOTYET /* XXX no callbacks on erase yet */
831  { int notifyFlags;
832  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
833  xx = rpmtsSetNotifyCallback(ts,
834  rpmShowProgress, (void *) ((long)notifyFlags));
835  }
836 #endif
837 
838  (void) rpmtsSetGoal(ts, TSM_ERASE);
839 
840  for (arg = argv; *arg; arg++) {
841  rpmmi mi;
842 
843  /* XXX HACK to get rpmdbFindByLabel out of the API */
844  mi = rpmtsInitIterator(ts, RPMTAG_NVRA, *arg, 0);
845  if (mi == NULL) {
846  rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
847  numFailed++;
848  } else {
849  Header h; /* XXX iterator owns the reference */
850  int count = 0;
851  while ((h = rpmmiNext(mi)) != NULL) {
852  uint32_t hdrNum = rpmmiInstance(mi);
853 
854  if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) {
855  rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages\n"),
856  *arg);
857  numFailed++;
858  /*@innerbreak@*/ break;
859  }
860  if (hdrNum) {
861  (void) rpmtsAddEraseElement(ts, h, hdrNum);
862  numRPMS++;
863  }
864  }
865  }
866  mi = rpmmiFree(mi);
867  }
868 
869  if (numFailed == 0 && numRPMS > 0) {
871  && (rc = rpmcliInstallCheck(ts)) != 0)
872  numFailed = numRPMS;
873 
874  if (numFailed == 0
876  && (rc = rpmcliInstallOrder(ts)) != 0)
877  numFailed = numRPMS;
878 
879  /* Drop added/available package indices and dependency sets. */
880  rpmtsClean(ts);
881 
882  if (numFailed == 0
884  numFailed += (rc < 0 ? numRPMS : rc);
885 
886  }
887 
888  rpmtsEmpty(ts);
889 
890  return numFailed;
891 }
892 
893 int rpmInstallSource(rpmts ts, const char * arg,
894  const char ** specFilePtr, const char ** cookie)
895 {
896  FD_t fd = Fopen(arg, "r%{?_rpmgio}");
897  rpmRC rc = RPMRC_FAIL; /* assume failure */
898 
899  if (fd == NULL || Ferror(fd)) {
900  rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
901  goto exit;
902  }
903 
904  if (rpmIsVerbose())
905  fprintf(stdout, _("Installing %s\n"), arg);
906 
907  {
908  rpmVSFlags nvsflags, ovsflags;
909  nvsflags = rpmtsVSFlags(ts);
910  VSF_SET(nvsflags, NEEDPAYLOAD);
911  ovsflags = rpmtsSetVSFlags(ts, nvsflags);
912  rc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
913  ovsflags = rpmtsSetVSFlags(ts, ovsflags);
914  }
915  if (rc != RPMRC_OK)
916  rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), arg);
917 
918 exit:
919  if (fd != NULL) (void) Fclose(fd);
920 
921  return (rc == RPMRC_OK ? 0 : 1);
922 }
rpmRelocation relocations
Definition: rpmcli.h:683
#define FTS_SLNONE
Definition: fts.h:141
#define QVA_ISSET(_qvaflags, _FLAG)
Definition: rpminstall.c:54
const char * str
Definition: rpmtag.h:73
rpmTag tag
Definition: rpmtag.h:503
int rpmErase(rpmts ts, QVA_t ia, const char **argv)
Erase binary rpm package.
Definition: rpminstall.c:781
int rpmgiRc(rpmgi gi)
Return current iteration item(s) exit code.
Definition: rpmgi.c:861
const char ** argv
Definition: rpmtag.h:75
rpmdepFlags depFlags
Definition: rpmcli.h:671
miRE mireNew(rpmMireMode mode, int tag)
Create pattern container.
Definition: mire.c:113
FTS * Fts_open(char *const *argv, int options, int(*compar)(const FTSENT **, const FTSENT **))
Create a handle for file hierarchy traversal.
Definition: fts.c:207
int Fcntl(FD_t fd, int op, void *lip)
fcntl(2) clone.
Definition: rpmio.c:3016
#define RMIL_GLOBAL
Definition: rpmmacro.h:70
int rpmcliPackagesTotal
Definition: rpminstall.c:63
const char bson_timestamp_t * ts
Definition: bson.h:1004
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.
char * xstrdup(const char *str)
Definition: rpmmalloc.c:321
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2840
rpmuint64_t rpmcliProgressTotal
Definition: rpminstall.c:71
int rpmtsAddInstallElement(rpmts ts, Header h, fnpyKey key, int upgrade, rpmRelocation relocs)
Add package to be installed to transaction set.
Definition: depends.c:547
rpmgi rpmgiFree(rpmgi gi)
Destroy a generalized iterator.
rpmuint64_t rpmcliProgressCurrent
Definition: rpminstall.c:69
char * rpmGetPath(const char *path,...)
Return (malloc'ed) expanded, canonicalized, file path.
Definition: macro.c:3445
enum rpmprobFilterFlags_e rpmprobFilterFlags
struct headerToken_s * Header
Definition: rpmtag.h:22
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2231
#define FTS_W
Definition: fts.h:142
void rpmpsPrint(FILE *fp, rpmps ps)
Print problems to file handle.
Definition: rpmps.c:346
The Header data structure.
int mireRegcomp(miRE mire, const char *pattern)
Compile pattern match.
Definition: mire.c:332
int argvAppend(ARGV_t *argvp, ARGV_t av)
Append one argv array to another.
Definition: argv.c:216
rpmQueryFlags qva_flags
Definition: rpmcli.h:633
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
#define FTS_SL
Definition: fts.h:140
FD_t fdLink(void *cookie, const char *msg)
static rpmVSFlags vsflags
Definition: rpmcache.c:547
Definition: rpmdb.c:436
int rpmtsSetNotifyCallback(rpmts ts, rpmCallbackFunction notify, rpmCallbackData notifyData)
Set transaction notify callback function and argument.
Definition: rpmts.c:1460
int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
Install/erase package elements in a transaction set, reporting problems.
Definition: rpminstall.c:357
Header rpmgiHeader(rpmgi gi)
Return current iteration header.
Definition: rpmgi.c:847
enum rpmCallbackType_e rpmCallbackType
Bit(s) to identify progress callbacks.
rpmuint32_t arbtid
Definition: rpmcli.h:675
#define FTS_NS
Definition: fts.h:138
void addMacro(MacroContext mc, const char *n, const char *o, const char *b, int level)
Add macro to context.
Definition: macro.c:2786
#define VSF_SET(_vsflags, _FLAG)
Definition: rpminstall.c:57
short fts_level
Definition: fts.h:127
static const char * rpmcliWalkFirst(ARGV_t av, miRE mire)
Definition: rpminstall.c:393
int Fadvise(FD_t fd, off_t offset, off_t length, int advice)
posix_fadvise(2) clone.
Definition: rpmrpc.c:1495
int rpmcliInstallProblems(rpmts ts, const char *msg, int rc)
Report package problems (if any).
Definition: rpminstall.c:311
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
int rpmcliInstallOrder(rpmts ts)
Order package elements in a transaction set, reporting problems.
Definition: rpminstall.c:350
int rpmcliInstallCheck(rpmts ts)
Check package element dependencies in a transaction set, reporting problems.
Definition: rpminstall.c:343
Command line option information.
Definition: rpmcli.h:630
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6730
int rpmcliHashesTotal
Definition: rpminstall.c:67
int rpmpsNumProblems(rpmps ps)
Return number of problems in set.
Definition: rpmps.c:70
char * alloca()
u_short fts_info
Definition: fts.h:143
rpmtransFlags rpmtsSetFlags(rpmts ts, rpmtransFlags transFlags)
Set transaction flags, i.e.
Definition: rpmts.c:1347
int rpmGlob(const char *patterns, int *argcPtr, const char ***argvPtr)
Return URL path(s) from a (URL prefixed) pattern glob.
Definition: macro.c:2611
struct _HE_s * HE_t
Definition: rpmtag.h:59
#define FTS_D
Definition: fts.h:129
void delMacro(MacroContext mc, const char *n)
Delete macro from context.
Definition: macro.c:2825
miRE mireFree(miRE mire)
Free pattern container.
static const char * rpmcliInstallElementPath(rpmts ts, const char *arg)
Definition: rpminstall.c:452
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * ptr
Definition: rpmtag.h:67
rpmgi rpmgiNew(rpmts ts, int tag, const void *keyp, size_t keylen)
Return a generalized iterator.
Definition: rpmgi.c:543
#define VSF_CLR(_vsflags, _FLAG)
Definition: rpminstall.c:58
#define FTS_NSOK
Definition: fts.h:139
FD_t fdFree(FD_t fd, const char *msg)
enum rpmgiFlags_e rpmgiFlags
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
rpmRC rpmInstallSourcePackage(rpmts ts, void *_fd, const char **specFilePtr, const char **cookie)
Install source package.
Definition: psm.c:212
#define FTS_COMFOLLOW
Definition: fts.h:87
const char const bson * data
Definition: mongo.h:463
rpmTagData p
Definition: rpmtag.h:506
unsigned long long rpmuint64_t
Definition: rpmiotypes.h:29
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
struct miRE_s * miRE
Definition: mire.h:60
int rpmtsNElements(rpmts ts)
Return number of (ordered) transaction set elements.
Definition: rpmts.c:1308
#define FTS_DEFAULT
Definition: fts.h:131
rpmtransFlags transFlags
Definition: rpmcli.h:672
#define FTS_DC
Definition: fts.h:130
int rpmInstallSource(rpmts ts, const char *arg, const char **specFilePtr, const char **cookie)
Install source rpm package.
Definition: rpminstall.c:893
Routines to expand a manifest containing glob expressions into an argv list.
#define RPMDBI_FTSWALK
Definition: rpmtag.h:487
Structure(s) used for dependency tag sets.
#define FTS_DOT
Definition: fts.h:133
rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
Load iterator args.
Definition: rpmgi.c:866
rpmQVSources qva_source
Definition: rpmcli.h:631
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 * newPath
Definition: rpmfi.c:63
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
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
Definition: mire.c:396
Definition: fts.h:54
pgpVSFlags rpmVSFlags
Bit(s) to control digest and signature verification.
Definition: rpmts.h:35
Header headerFree(Header h)
Dereference a header instance.
int rpmioFtsOpts
Definition: poptIO.c:539
FTSENT * Fts_read(FTS *sp)
Return next node in the file hierarchy traversal.
Definition: fts.c:467
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3252
void rpmtsSetARBGoal(rpmts ts, rpmuint32_t goal)
Set autorollback goal.
Definition: rpmts.c:886
const char const char int arg
Definition: mongo.h:777
int rpmcliInstall(rpmts ts, QVA_t ia, const char **argv)
Install/upgrade/freshen binary rpm package.
Definition: rpminstall.c:535
rpmInstallInterfaceFlags installInterfaceFlags
Definition: rpmcli.h:674
static void printHash(const rpmuint64_t amount, const rpmuint64_t total)
Print a CLI progress bar.
Definition: rpminstall.c:79
rpmmi rpmmiFree(rpmmi mi)
Destroy rpm database iterator.
int Fclose(FD_t fd)
fclose(3) clone.
Definition: rpmio.c:2534
const char const bson int mongo_write_concern int flags
Definition: mongo.h:485
rpmprobFilterFlags probFilter
Definition: rpmcli.h:673
#define FTS_DNR
Definition: fts.h:132
char * fts_accpath
Definition: fts.h:113
int Fts_set(FTS *sp, FTSENT *p, int instr)
Modify the traversal for a file set member.
Definition: fts.c:688
rpmps rpmpsFree(rpmps ps)
Destroy a problem set.
Header headerLink(Header h)
Reference a header instance.
#define FTS_INIT
Definition: fts.h:137
struct rpmgi_s * rpmgi
Generalized iterator.
Definition: rpmtypes.h:53
enum rpmRC_e rpmRC
RPM return codes.
#define RPMDBI_ARGLIST
Definition: rpmtag.h:486
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2951
Definition: rpmtag.h:502
const char const int i
Definition: bson.h:778
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
const char const bson * key
Definition: mongo.h:717
Definition: fts.h:102
rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags)
Set dependency flags, i.e.
Definition: rpmts.c:1368
rpmps rpmtsProblems(rpmts ts)
Return current transaction set problems.
Definition: rpmts.c:584
enum rpmtransFlags_e rpmtransFlags
Bit(s) to control rpmtsRun() operation.
rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
Set verify signatures flag(s).
Definition: rpmts.c:845
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
const void * fnpyKey
Definition: rpmiotypes.h:134
Structures and prototypes used for an "rpmts" transaction set.
Header rpmmiNext(rpmmi mi)
Return next package header from iteration.
Definition: rpmdb.c:2252
int(* rpmtsRun)(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
Process all package elements in a transaction set.
Definition: transaction.c:2307
rpmVSFlags rpmtsVSFlags(rpmts ts)
Get verify signatures flag(s).
Definition: rpmts.c:840
static rpmRC rpmcliEraseElement(rpmts ts, const char *arg)
Definition: rpminstall.c:365
Structure(s) and routine(s) used for EVR parsing and comparison.
int rpmtsAddEraseElement(rpmts ts, Header h, uint32_t hdrNum)
Add package to be erased to transaction set.
Definition: depends.c:834
int rpmcliHashesCurrent
Definition: rpminstall.c:65
int(* rpmtsCheck)(rpmts ts)
Perform dependency resolution on the transaction set.
Definition: depends.c:2097
int argvSplit(ARGV_t *argvp, const char *str, const char *seps)
Split a string into an argv array.
Definition: argv.c:233
#define FTS_LOGICAL
Definition: fts.h:88
#define rpmIsVerbose()
Definition: rpmcb.h:21
int Fts_close(FTS *sp)
Destroy a file hierarchy traversal handle.
Definition: fts.c:380
rpmRC rpmgiNext(rpmgi gi)
Perform next iteration step.
Definition: rpmgi.c:584
#define FTS_F
Definition: fts.h:136
Header rpmgiReadHeader(rpmgi gi, const char *path)
Return header from package.
Definition: rpmgi.c:156
#define _(Text)
Definition: system.h:29
const char * rpmgiHdrPath(rpmgi gi)
Return current header path.
Definition: rpmgi.c:842
void * rpmShowProgress(const void *arg, const rpmCallbackType what, const rpmuint64_t amount, const rpmuint64_t total, fnpyKey key, void *data)
The rpm CLI generic transaction callback handler.
Definition: rpminstall.c:126
#define FTS_DP
Definition: fts.h:134
ARGstr_t * ARGV_t
Definition: argv.h:12
Access RPM indices using Berkeley DB interface(s).
#define D_(Text)
Definition: system.h:526
int rpmcliInstallSuggests(rpmts ts)
Report packages(if any) that satisfy unresolved dependencies.
Definition: rpminstall.c:326
unsigned int rpmmiCount(rpmmi mi)
Return number of elements in rpm database iterator.
Definition: rpmdb.c:1763
const char * oldPath
Definition: rpmfi.c:61
#define FTS_NOSTAT
Definition: fts.h:90
In Memoriam: Steve Taylor staylor@redhat.com was here, now he's not.
int(* rpmtsOrder)(rpmts ts)
Determine package order in a transaction set according to dependencies.
Definition: order.c:2311
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3326
#define FTS_ERR
Definition: fts.h:135
void rpmtsEmpty(rpmts ts)
Re-create an empty transaction set.
Definition: rpmts.c:625
int rpmVersionCompare(Header A, Header B)
Definition: rpmevr.c:425
tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal)
Set goal of transaction set.
Definition: rpmts.c:1415
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:598
#define FTS_SKIP
Definition: fts.h:152