rpm  5.4.10
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  fd = fdLink(fd, "persist (showProgress)");
173 
174 #if defined(POSIX_FADV_WILLNEED)
175  (void) Fadvise(fd, 0, 0, POSIX_FADV_WILLNEED);
176 #endif
177 
178 /*@+voidabstract@*/
179  return (void *)fd;
180 /*@=voidabstract@*/
181  /*@notreached@*/ break;
182 
184  /*@-type@*/ /* FIX: still necessary? */
185  fd = fdFree(fd, "persist (showProgress)");
186  /*@=type@*/
187  if (fd != NULL) {
188  xx = Fclose(fd);
189  fd = NULL;
190  }
191  break;
192 
194  rpmcliHashesCurrent = 0;
195  if (h == NULL || !(flags & INSTALL_LABEL))
196  break;
197  /* @todo Remove headerSprintf() on a progress callback. */
198  if (flags & INSTALL_HASH) {
199  s = headerSprintf(h, "%{NAME}",
200  NULL, rpmHeaderFormats, NULL);
201  if (isatty (STDOUT_FILENO))
202  fprintf(stdout, "%4d:%-23.23s", (int)rpmcliProgressCurrent + 1, s);
203  else
204  fprintf(stdout, "%-28.28s", s);
205  (void) fflush(stdout);
206  s = _free(s);
207  } else {
208  char * t = rpmExpand("%{?___NVRA}%{!?___NVRA:%%{NAME}-%%{VERSION}-%%{RELEASE}}", NULL);
209  s = headerSprintf(h, t, NULL, rpmHeaderFormats, NULL);
210  fprintf(stdout, "%s\n", s);
211  (void) fflush(stdout);
212  s = _free(s);
213  t = _free(t);
214  }
215  break;
216 
219 /*@+relaxtypes@*/
220  if (flags & INSTALL_PERCENT)
221  fprintf(stdout, "%%%% %f\n", (double) (total
222  ? ((((float) amount) / total) * 100)
223  : 100.0));
224  else if (flags & INSTALL_HASH)
225  printHash(amount, total);
226 /*@=relaxtypes@*/
227  (void) fflush(stdout);
228  break;
229 
231  rpmcliHashesCurrent = 0;
232  rpmcliProgressTotal = 1;
233  rpmcliProgressCurrent = 0;
234  if (!(flags & INSTALL_LABEL))
235  break;
236  if (flags & INSTALL_HASH)
237  fprintf(stdout, "%-28s", _("Preparing..."));
238  else
239  fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
240  (void) fflush(stdout);
241  break;
242 
244  if (flags & INSTALL_HASH)
245  printHash(1, 1); /* Fixes "preparing..." progress bar */
246  rpmcliProgressTotal = rpmcliPackagesTotal;
247  rpmcliProgressCurrent = 0;
248  break;
249 
251  rpmcliHashesCurrent = 0;
252  rpmcliProgressTotal = total;
253  rpmcliProgressCurrent = 0;
254  if (!(flags & INSTALL_LABEL))
255  break;
256  if (flags & INSTALL_HASH)
257  fprintf(stdout, "%-28s\n", _("Repackaging..."));
258  else
259  fprintf(stdout, "%s\n", _("Repackaging erased files..."));
260  (void) fflush(stdout);
261  break;
262 
264  if (amount && (flags & INSTALL_HASH))
265  printHash(1, 1); /* Fixes "preparing..." progress bar */
266  break;
267 
269  rpmcliProgressTotal = total;
270  rpmcliProgressCurrent = total;
271  if (flags & INSTALL_HASH)
272  printHash(1, 1); /* Fixes "preparing..." progress bar */
273  rpmcliProgressTotal = rpmcliPackagesTotal;
274  rpmcliProgressCurrent = 0;
275  if (!(flags & INSTALL_LABEL))
276  break;
277  if (flags & INSTALL_HASH)
278  fprintf(stdout, "%-28s\n", _("Upgrading..."));
279  else
280  fprintf(stdout, "%s\n", _("Upgrading packages..."));
281  (void) fflush(stdout);
282  break;
283 
285  break;
287  break;
289  break;
291  break;
293  break;
295  break;
297  break;
299  break;
300  case RPMCALLBACK_UNKNOWN:
301  default:
302  break;
303  }
304 
305  return rc;
306 }
307 
308 int rpmcliInstallProblems(rpmts ts, const char * msg, int rc)
309  /*@globals fileSystem @*/
310  /*@modifies ts, fileSystem @*/
311 {
312  rpmps ps = rpmtsProblems(ts);
313 
314  if (rc && rpmpsNumProblems(ps) > 0) {
315  if (msg)
316  rpmlog(RPMLOG_ERR, "%s:\n", msg);
317  rpmpsPrint(NULL, ps);
318  }
319  ps = rpmpsFree(ps);
320  return rc;
321 }
322 
324 {
325  if (ts->suggests != NULL && ts->nsuggests > 0) {
326  const char * s;
327  int i;
328 
329  rpmlog(RPMLOG_NOTICE, _(" Suggested resolutions:\n"));
330  for (i = 0; i < ts->nsuggests && (s = (char *)ts->suggests[i]) != NULL;
331  s = _free(s), ts->suggests[i++] = NULL)
332  {
333  rpmlog(RPMLOG_NOTICE, "\t%s\n", s);
334  }
335  ts->suggests = _free(ts->suggests);
336  }
337  return 0;
338 }
339 
341 {
342 /*@-evalorder@*/
343  return rpmcliInstallProblems(ts, _("Failed dependencies"), rpmtsCheck(ts));
344 /*@=evalorder@*/
345 }
346 
348 {
349 /*@-evalorder@*/
350  return rpmcliInstallProblems(ts, _("Ordering problems"), rpmtsOrder(ts));
351 /*@=evalorder@*/
352 }
353 
354 int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
355 {
356 /*@-evalorder@*/
357  return rpmcliInstallProblems(ts, _("Install/Erase problems"),
358  rpmtsRun(ts, okProbs, ignoreSet));
359 /*@=evalorder@*/
360 }
361 
362 static rpmRC rpmcliEraseElement(rpmts ts, const char * arg)
363  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
364  /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
365 {
366  rpmmi mi;
367  Header h;
368  rpmRC rc = RPMRC_OK;
369  int xx;
370 
371  mi = rpmtsInitIterator(ts, RPMTAG_NVRA, arg, 0);
372  if (mi == NULL)
373  return RPMRC_NOTFOUND;
374 
375  while ((h = rpmmiNext(mi)) != NULL) {
376  uint32_t hdrNum = rpmmiInstance(mi);
377 
378  if (hdrNum == 0) { /* XXX can't happen. */
379  rc = RPMRC_FAIL;
380  break;
381  }
382  xx = rpmtsAddEraseElement(ts, h, hdrNum);
383  }
384  mi = rpmmiFree(mi);
385 
386  /* XXX FIXME: return rc? */
387  return (rpmRC)0;
388 }
389 
390 static const char * rpmcliWalkFirst(ARGV_t av, miRE mire)
391  /*@globals fileSystem, internalState @*/
392  /*@modifies mire, fileSystem, internalState @*/
393 {
394  /* XXX use global ftsOpts? */
395  /* XXX changing FTS_LOGICAL to FTS_PHYSICAL prevents symlink follow. */
396  /* XXX FTS_NOCHDIR is automatically assumed for URI's */
397  int _ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
398  FTS * ftsp = NULL;
399  FTSENT * fts;
400  const char * fn = NULL;
401  int fts_level = 1;
402  int xx;
403 
404  if (av != NULL && av[0] != NULL)
405  ftsp = Fts_open((char *const *)av, _ftsOpts, NULL);
406  if (ftsp != NULL)
407  while((fts = Fts_read(ftsp)) != NULL) {
408  switch (fts->fts_info) {
409  /* No-op conditions. */
410  case FTS_D: /* preorder directory */
411  case FTS_DP: /* postorder directory */
412  /* XXX Don't recurse downwards, all elements should be files. */
413  if (fts_level > 0 && fts->fts_level >= fts_level)
414  xx = Fts_set(ftsp, fts, FTS_SKIP);
415  /*@fallthrough@*/
416  case FTS_DOT: /* dot or dot-dot */
417  continue;
418  /*@notreached@*/ /*@switchbreak@*/ break;
419  case FTS_F: /* regular file */
420  if (mireRegexec(mire, fts->fts_accpath, 0) < 0)
421  continue;
422  /*@switchbreak@*/ break;
423  /* Error conditions. */
424  case FTS_NS: /* stat(2) failed */
425  case FTS_DNR: /* unreadable directory */
426  case FTS_ERR: /* error; errno is set */
427  case FTS_DC: /* directory that causes cycles */
428  case FTS_DEFAULT: /* none of the above */
429  case FTS_INIT: /* initialized only */
430  case FTS_NSOK: /* no stat(2) requested */
431  case FTS_SL: /* symbolic link */
432  case FTS_SLNONE: /* symbolic link without target */
433  case FTS_W: /* whiteout object */
434  default:
435  goto exit;
436  /*@notreached@*/ /*@switchbreak@*/ break;
437  }
438 
439  /* Stop on first file that matches. */
440  fn = xstrdup(fts->fts_accpath);
441  break;
442  }
443 
444 exit:
445  xx = Fts_close(ftsp);
446  return fn;
447 }
448 
449 static const char * rpmcliInstallElementPath(/*@unused@*/ rpmts ts,
450  const char * arg)
451  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
452  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
453 {
454  /* A glob pattern list to match repository directories. */
455  const char * fn = rpmExpand(
456  "%{?_rpmgi_pattern_glob}"
457  "%{!?_rpmgi_pattern_glob:.}",
458  NULL
459  );
460  /* A regex pattern list to match candidate *.rpm files. */
461  const char * mirePattern = rpmExpand(
462  "%{?_rpmgi_pattern_regex:%{_rpmgi_pattern_regex ", arg, "}}"
463  "%{!?_rpmgi_pattern_regex:", arg, "-[^-]+-[^-]+\\.[^.]+\\.rpm$}",
464  NULL
465  );
466  miRE mire = mireNew(RPMMIRE_REGEX, 0);
467  ARGV_t dav = NULL;
468  int dac = 0;
469  ARGV_t av = NULL;
470  int xx = mireRegcomp(mire, mirePattern);
471  int i;
472 
473  /* Get list of candidate repository patterns. */
474  xx = argvSplit(&dav, fn, ":");
475  fn = _free(fn);
476  if (xx || dav == NULL)
477  goto exit;
478 
479  dac = argvCount(dav);
480  for (i = 0; i < dac; i++) {
481  ARGV_t nav = NULL;
482  int nac = 0;
483 
484  /* Make sure only directory paths are matched. */
485  fn = rpmGetPath(dav[i], "/", NULL);
486  xx = rpmGlob(fn, &nac, &nav);
487 
488  if (nav != NULL)
489  for (i = 0; i < nac; i++) {
490  const char * t = nav[i];
491  size_t nt = strlen(t);
492 
493  /* Make sure that final directory paths have trailing '/' */
494  if (!(nt > 0 && t[nt-1] == '/'))
495  continue;
496 
497  t = rpmExpand(t, "/", NULL);
498  nav[i] = _free(nav[i]);
499  nav[i] = t;
500  }
501 
502  /* Append matches to list of repository directories. */
503  if (nac > 0 && nav != NULL)
504  xx = argvAppend(&av, nav);
505  nav = argvFree(nav);
506  nac = 0;
507  fn = _free(fn);
508  }
509 
510  /* Walk (possibly multi-root'd) directories, until 1st match is found. */
511  fn = rpmcliWalkFirst(av, mire);
512 
513 exit:
514  av = argvFree(av);
515  dav = argvFree(dav);
516  mire = mireFree(mire);
517  mirePattern = _free(mirePattern);
518 
519  return fn;
520 }
521 
522 /*@-redef@*/ /* XXX Add rpmfi methods to make rpmRelocation opaque. */
523 struct rpmRelocation_s {
524 /*@only@*/ /*@null@*/
525  const char * oldPath;
526 /*@only@*/ /*@null@*/
527  const char * newPath;
528 };
529 /*@=redef@*/
530 
532 int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv)
533 {
534  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
535  ARGV_t avfn = NULL;
536  int acfn = 0;
537  int numFailed = 0;
538  int numRPMS = 0;
539  rpmRelocation relocations = NULL;
540  rpmVSFlags vsflags, ovsflags;
541  rpmRC rpmrc;
542  int rc;
543  int xx;
544 
545  if (argv == NULL) goto exit;
546 
547  (void) rpmtsSetGoal(ts, TSM_INSTALL);
548  rpmcliPackagesTotal = 0;
549 
550  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
551  ia->transFlags = (rpmtransFlags)
553 
554  (void) rpmtsSetFlags(ts, ia->transFlags);
555  (void) rpmtsSetDFlags(ts, ia->depFlags);
556 
557  /* Display and set autorollback goal. */
558  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
559  if (ia->arbtid) {
560  time_t ttid = (time_t)ia->arbtid;
561  rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
562  ctime(&ttid), ia->arbtid);
563  rpmtsSetARBGoal(ts, ia->arbtid);
564  }
565  }
566 
568  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_erase}");
569  else
570  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_install}");
571  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
572 #if defined(SUPPORT_NOSIGNATURES)
573  if (!QVA_ISSET(ia->qva_flags, DIGEST)) {
574  VSF_SET(vsflags, NOSHA1HEADER);
575  VSF_SET(vsflags, NOMD5HEADER);
576  VSF_SET(vsflags, NOSHA1);
577  VSF_SET(vsflags, NOMD5);
578  }
579  if (!QVA_ISSET(ia->qva_flags, SIGNATURE)) {
580  VSF_SET(vsflags, NODSAHEADER);
581  VSF_SET(vsflags, NORSAHEADER);
582  VSF_SET(vsflags, NODSA);
583  VSF_SET(vsflags, NORSA);
584  }
585  if (!QVA_ISSET(ia->qva_flags, HDRCHK)) {
586  VSF_SET(vsflags, NOHDRCHK);
587  }
588  VSF_SET(vsflags, NEEDPAYLOAD);
589 #endif
590  ovsflags = rpmtsSetVSFlags(ts, vsflags);
591 
592  { int notifyFlags;
593  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
594  xx = rpmtsSetNotifyCallback(ts,
595  rpmShowProgress, (void *) ((long)notifyFlags));
596  }
597 
598  if ((relocations = ia->relocations) != NULL) {
599  while (relocations->oldPath)
600  relocations++;
601  if (relocations->newPath == NULL)
602  relocations = NULL;
603  }
604 
605  { /* start-of-transaction-build */
606  int tag = (ia->qva_source == RPMQV_FTSWALK)
608  rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
609  rpmgiFlags _giFlags = RPMGI_NONE;
610  const char * fn = NULL;;
611 
612 /*@-mods@*/
613  if (rpmioFtsOpts == 0)
615 /*@=mods@*/
616  rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, _giFlags);
617  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
618  Header h;
619 
620  fn = _free(fn);
621  fn = xstrdup(rpmgiHdrPath(gi));
622 
623  /* === Check for "+bing" lookaside paths within install transaction. */
624  if (fn[0] == '+') {
625  const char * nfn;
626  addMacro(NULL, "NEVRA", NULL, &fn[1], RMIL_GLOBAL);
627  nfn = rpmcliInstallElementPath(ts, &fn[1]);
628  delMacro(NULL, "NEVRA");
629  if (nfn == NULL) {
630  rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be found\n"), fn);
631  numFailed++; /* XXX multiple erasures? */
632  continue;
633  }
634  fn = _free(fn);
635  fn = nfn;
636  /* XXX hack into rpmgi innards for now ... */
637  h = rpmgiReadHeader(gi, fn);
638  if (h != NULL)
639  gi->h = headerLink(h);
640  (void)headerFree(h);
641  h = NULL;
642  }
643 
644  /* === Check for "-bang" erasures within install transaction. */
645  if (fn[0] == '-') {
646  switch (rpmcliEraseElement(ts, &fn[1])) {
647  case RPMRC_OK:
648  numRPMS++; /* XXX multiple erasures? */
649  /*@switchbreak@*/ break;
650  case RPMRC_NOTFOUND:
651  default:
652  rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be erased\n"), fn);
653  numFailed++; /* XXX multiple erasures? */
654  goto exit;
655  /*@notreached@*/ /*@switchbreak@*/ break;
656  }
657  continue;
658  }
659 
660  h = rpmgiHeader(gi);
661  if (h == NULL) {
662  numFailed++;
663  continue;
664  }
665 
666  /* === Check for relocatable package. */
667  if (relocations) {
668  he->tag = RPMTAG_PREFIXES;
669  xx = headerGet(h, he, 0);
670  if (xx && he->c == 1) {
671  relocations->oldPath = xstrdup(he->p.argv[0]);
672  he->p.ptr = _free(he->p.ptr);
673  } else {
674  he->p.ptr = _free(he->p.ptr);
675  he->tag = RPMTAG_NVRA;
676  xx = headerGet(h, he, 0);
678  _("package %s is not relocatable\n"), he->p.str);
679  he->p.ptr = _free(he->p.ptr);
680  numFailed++;
681  goto exit;
682  /*@notreached@*/
683  }
684  }
685 
686  /* === On --freshen, verify package is installed and newer. */
688  rpmmi mi;
689  Header oldH;
690  int count;
691 
692  he->tag = RPMTAG_NAME;
693  xx = headerGet(h, he, 0);
694 assert(xx != 0 && he->p.str != NULL);
695  mi = rpmtsInitIterator(ts, RPMTAG_NAME, he->p.str, 0);
696  he->p.ptr = _free(he->p.ptr);
697  count = rpmmiCount(mi);
698  while ((oldH = rpmmiNext(mi)) != NULL) {
699  if (rpmVersionCompare(oldH, h) < 0)
700  /*@innercontinue@*/ continue;
701  /* same or newer package already installed */
702  count = 0;
703  /*@innerbreak@*/ break;
704  }
705  mi = rpmmiFree(mi);
706  if (count == 0)
707  continue;
708  /* Package is newer than those currently installed. */
709  }
710 
711  /* === Add binary package to transaction set. */
712  xx = argvAdd(&avfn, fn);
713  rc = rpmtsAddInstallElement(ts, h, (fnpyKey)avfn[acfn++],
715  ia->relocations);
716 
717  if (relocations)
718  relocations->oldPath = _free(relocations->oldPath);
719 
720  numRPMS++;
721  }
722 
723  /* XXX disambiguate end-of-iteration from item failures. */
724  if (rpmrc == RPMRC_NOTFOUND)
725  rpmrc = (rpmRC) rpmgiRc(gi);
726 
727  fn = _free(fn);
728  gi = rpmgiFree(gi);
729 
730  } /* end-of-transaction-build */
731 
732  /* XXX exit if the iteration failed. */
733  if (rpmrc != RPMRC_OK)
734  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
735  if (numFailed) goto exit;
736 
737  if (numRPMS) {
739  && (rc = rpmcliInstallCheck(ts)) != 0) {
740  numFailed = numRPMS;
741  (void) rpmcliInstallSuggests(ts);
742  }
743 
745  && (rc = rpmcliInstallOrder(ts)) != 0)
746  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
747 
748  /* Drop added/available package indices and dependency sets. */
749  rpmtsClean(ts);
750 
751  /* XXX Avoid empty transaction msg, run iff there are elements. */
752  if (numFailed == 0 && rpmtsNElements(ts) > 0
753  && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter)) != 0) {
754  if (rc > 0)
755  numFailed = rc;
756  else
757  numFailed = (numRPMS ? numRPMS : 1); /* XXX error on no-op. */
758  }
759  }
760 
761  if (numFailed) goto exit;
762 
763 exit:
764  avfn = argvFree(avfn);
765 
766 #ifdef NOTYET /* XXX grrr, segfault in selabel_close */
768  matchpathcon_fini();
769 #endif
770 
771  rpmtsEmpty(ts);
772 
773  return numFailed;
774 }
775 
776 int rpmErase(rpmts ts, QVA_t ia, const char ** argv)
777 {
778  const char ** arg;
779  int numFailed = 0;
780  int numRPMS = 0;
781  rpmVSFlags vsflags, ovsflags;
782  int rc;
783 
784  if (argv == NULL) return 0;
785 
786  vsflags = (rpmVSFlags) rpmExpandNumeric("%{?_vsflags_erase}");
787  vsflags = (rpmVSFlags) 0; /* XXX FIXME: ignore default disablers. */
788 #if defined(SUPPORT_NOSIGNATURES)
789  if (!QVA_ISSET(ia->qva_flags, DIGEST)) {
790  VSF_SET(vsflags, NOSHA1HEADER);
791  VSF_SET(vsflags, NOMD5HEADER);
792  VSF_SET(vsflags, NOSHA1);
793  VSF_SET(vsflags, NOMD5);
794  }
795  if (!QVA_ISSET(ia->qva_flags, SIGNATURE)) {
796  VSF_SET(vsflags, NODSAHEADER);
797  VSF_SET(vsflags, NORSAHEADER);
798  VSF_SET(vsflags, NODSA);
799  VSF_SET(vsflags, NORSA);
800  }
801  if (!QVA_ISSET(ia->qva_flags, HDRCHK)) {
802  VSF_SET(vsflags, NOHDRCHK);
803  }
804  VSF_CLR(vsflags, NEEDPAYLOAD); /* XXX needed? */
805 #endif
806  ovsflags = rpmtsSetVSFlags(ts, vsflags);
807 
808  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
809  ia->transFlags = (rpmtransFlags)
811 
812  (void) rpmtsSetFlags(ts, ia->transFlags);
813  (void) rpmtsSetDFlags(ts, ia->depFlags);
814 
815  /* Display and set autorollback goal. */
816  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
817  if (ia->arbtid) {
818  time_t ttid = (time_t)ia->arbtid;
819  rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
820  ctime(&ttid), ia->arbtid);
821  rpmtsSetARBGoal(ts, ia->arbtid);
822  }
823  }
824 
825 #ifdef NOTYET /* XXX no callbacks on erase yet */
826  { int notifyFlags;
827  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
828  xx = rpmtsSetNotifyCallback(ts,
829  rpmShowProgress, (void *) ((long)notifyFlags));
830  }
831 #endif
832 
833  (void) rpmtsSetGoal(ts, TSM_ERASE);
834 
835  for (arg = argv; *arg; arg++) {
836  rpmmi mi;
837 
838  /* XXX HACK to get rpmdbFindByLabel out of the API */
839  mi = rpmtsInitIterator(ts, RPMTAG_NVRA, *arg, 0);
840  if (mi == NULL) {
841  rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
842  numFailed++;
843  } else {
844  Header h; /* XXX iterator owns the reference */
845  int count = 0;
846  while ((h = rpmmiNext(mi)) != NULL) {
847  uint32_t hdrNum = rpmmiInstance(mi);
848 
849  if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) {
850  rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages\n"),
851  *arg);
852  numFailed++;
853  /*@innerbreak@*/ break;
854  }
855  if (hdrNum) {
856  (void) rpmtsAddEraseElement(ts, h, hdrNum);
857  numRPMS++;
858  }
859  }
860  }
861  mi = rpmmiFree(mi);
862  }
863 
864  if (numFailed == 0 && numRPMS > 0) {
866  && (rc = rpmcliInstallCheck(ts)) != 0)
867  numFailed = numRPMS;
868 
869  if (numFailed == 0
871  && (rc = rpmcliInstallOrder(ts)) != 0)
872  numFailed = numRPMS;
873 
874  /* Drop added/available package indices and dependency sets. */
875  rpmtsClean(ts);
876 
877  if (numFailed == 0
879  numFailed += (rc < 0 ? numRPMS : rc);
880 
881  }
882 
883  rpmtsEmpty(ts);
884 
885  return numFailed;
886 }
887 
888 int rpmInstallSource(rpmts ts, const char * arg,
889  const char ** specFilePtr, const char ** cookie)
890 {
891  FD_t fd = Fopen(arg, "r%{?_rpmgio}");
892  rpmRC rc = RPMRC_FAIL; /* assume failure */
893 
894  if (fd == NULL || Ferror(fd)) {
895  rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
896  goto exit;
897  }
898 
899  if (rpmIsVerbose())
900  fprintf(stdout, _("Installing %s\n"), arg);
901 
902  {
903  rpmVSFlags nvsflags, ovsflags;
904  nvsflags = rpmtsVSFlags(ts);
905  VSF_SET(nvsflags, NEEDPAYLOAD);
906  ovsflags = rpmtsSetVSFlags(ts, nvsflags);
907  rc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
908  ovsflags = rpmtsSetVSFlags(ts, ovsflags);
909  }
910  if (rc != RPMRC_OK)
911  rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), arg);
912 
913 exit:
914  if (fd != NULL) (void) Fclose(fd);
915 
916  return (rc == RPMRC_OK ? 0 : 1);
917 }
rpmRelocation relocations
Definition: rpmcli.h:687
#define FTS_SLNONE
Definition: fts.h:141
#define QVA_ISSET(_qvaflags, _FLAG)
Definition: rpminstall.c:54
const char * str
Definition: rpmtag.h:72
rpmTag tag
Definition: rpmtag.h:504
int rpmErase(rpmts ts, QVA_t ia, const char **argv)
Erase binary rpm package.
Definition: rpminstall.c:776
int rpmgiRc(rpmgi gi)
Return current iteration item(s) exit code.
Definition: rpmgi.c:859
const char ** argv
Definition: rpmtag.h:74
rpmdepFlags depFlags
Definition: rpmcli.h:675
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
#define RMIL_GLOBAL
Definition: rpmmacro.h:58
int rpmcliPackagesTotal
Definition: rpminstall.c:63
uint32_t rpmmiInstance(rpmmi mi)
Return header instance for current position of rpmdb iterator.
Definition: rpmdb.c:1743
Structures used for an "rpmte" transaction element.
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
FD_t Fopen(const char *path, const char *_fmode)
fopen(3) clone.
Definition: rpmio.c:2833
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:552
rpmgi rpmgiFree(rpmgi gi)
Destroy a generalized iterator.
rpmuint64_t rpmcliProgressCurrent
Definition: rpminstall.c:69
char * rpmGetPath(const char *path,...)
Return (malloc&#39;ed) expanded, canonicalized, file path.
Definition: macro.c:3310
enum rpmprobFilterFlags_e rpmprobFilterFlags
struct headerToken_s * Header
Definition: rpmtag.h:21
int headerGet(Header h, HE_t he, unsigned int flags)
Retrieve extension or tag value from a header.
Definition: header.c:2222
#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:334
int argvAppend(ARGV_t *argvp, ARGV_t av)
Append one argv array to another.
Definition: argv.c:216
rpmQueryFlags qva_flags
Definition: rpmcli.h:637
headerSprintfExtension rpmHeaderFormats
Table of query format extensions.
Definition: formats.c:305
#define FTS_SL
Definition: fts.h:140
int(* rpmtsOrder)(rpmts ts)
Determine package order in a transaction set according to dependencies.
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:1470
int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
Install/erase package elements in a transaction set, reporting problems.
Definition: rpminstall.c:354
Header rpmgiHeader(rpmgi gi)
Return current iteration header.
Definition: rpmgi.c:845
enum rpmCallbackType_e rpmCallbackType
Bit(s) to identify progress callbacks.
rpmuint32_t arbtid
Definition: rpmcli.h:679
#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:2684
#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:390
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:308
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:22
int rpmcliInstallOrder(rpmts ts)
Order package elements in a transaction set, reporting problems.
Definition: rpminstall.c:347
int rpmcliInstallCheck(rpmts ts)
Check package element dependencies in a transaction set, reporting problems.
Definition: rpminstall.c:340
Command line option information.
Definition: rpmcli.h:634
char * headerSprintf(Header h, const char *fmt, headerTagTableEntry tags, headerSprintfExtension exts, errmsg_t *errmsg)
Return formatted output string from header tags.
Definition: hdrfmt.c:6700
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:1357
int rpmGlob(const char *patterns, int *argcPtr, const char ***argvPtr)
Return URL path(s) from a (URL prefixed) pattern glob.
Definition: macro.c:2509
struct _HE_s * HE_t
Definition: rpmtag.h:58
#define FTS_D
Definition: fts.h:129
void delMacro(MacroContext mc, const char *n)
Delete macro from context.
Definition: macro.c:2723
miRE mireFree(miRE mire)
Free pattern container.
static const char * rpmcliInstallElementPath(rpmts ts, const char *arg)
Definition: rpminstall.c:449
const char * Fstrerror(FD_t fd)
strerror(3) clone.
Definition: rpmio.c:2401
void * ptr
Definition: rpmtag.h:66
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:210
#define FTS_COMFOLLOW
Definition: fts.h:87
rpmTagData p
Definition: rpmtag.h:507
unsigned long long rpmuint64_t
Definition: rpmiotypes.h:26
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
struct miRE_s * miRE
Definition: mire.h:60
int(* rpmtsCheck)(rpmts ts)
Perform dependency resolution on the transaction set.
Definition: depends.c:2080
int rpmtsNElements(rpmts ts)
Return number of (ordered) transaction set elements.
Definition: rpmts.c:1318
#define FTS_DEFAULT
Definition: fts.h:131
rpmtransFlags transFlags
Definition: rpmcli.h:676
#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:888
Routines to expand a manifest containing glob expressions into an argv list.
#define RPMDBI_FTSWALK
Definition: rpmtag.h:488
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:864
rpmQVSources qva_source
Definition: rpmcli.h:635
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:508
int mireRegexec(miRE mire, const char *val, size_t vallen)
Execute pattern match.
Definition: mire.c:398
Definition: fts.h:54
pgpVSFlags rpmVSFlags
Bit(s) to control digest and signature verification.
Definition: rpmts.h:30
Header headerFree(Header h)
Dereference a header instance.
int rpmioFtsOpts
Definition: poptIO.c:526
FTSENT * Fts_read(FTS *sp)
Return next node in the file hierarchy traversal.
Definition: fts.c:467
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
int(* rpmtsRun)(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
Process all package elements in a transaction set.
Definition: transaction.c:2353
void rpmtsSetARBGoal(rpmts ts, rpmuint32_t goal)
Set autorollback goal.
Definition: rpmts.c:884
int rpmcliInstall(rpmts ts, QVA_t ia, const char **argv)
Install/upgrade/freshen binary rpm package.
Definition: rpminstall.c:532
rpmInstallInterfaceFlags installInterfaceFlags
Definition: rpmcli.h:678
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
rpmprobFilterFlags probFilter
Definition: rpmcli.h:677
#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:487
int Ferror(FD_t fd)
ferror(3) clone.
Definition: rpmio.c:2944
Definition: rpmtag.h:503
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:429
Definition: fts.h:102
rpmdepFlags rpmtsSetDFlags(rpmts ts, rpmdepFlags depFlags)
Set dependency flags, i.e.
Definition: rpmts.c:1378
rpmps rpmtsProblems(rpmts ts)
Return current transaction set problems.
Definition: rpmts.c:582
enum rpmtransFlags_e rpmtransFlags
Bit(s) to control rpmtsRun() operation.
rpmVSFlags rpmtsSetVSFlags(rpmts ts, rpmVSFlags vsflags)
Set verify signatures flag(s).
Definition: rpmts.c:843
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:647
const void * fnpyKey
Definition: rpmiotypes.h:118
Structures and prototypes used for an "rpmts" transaction set.
Header rpmmiNext(rpmmi mi)
Return next package header from iteration.
Definition: rpmdb.c:2248
rpmVSFlags rpmtsVSFlags(rpmts ts)
Get verify signatures flag(s).
Definition: rpmts.c:838
static rpmRC rpmcliEraseElement(rpmts ts, const char *arg)
Definition: rpminstall.c:362
int rpmtsAddEraseElement(rpmts ts, Header h, uint32_t hdrNum)
Add package to be erased to transaction set.
Definition: depends.c:839
int rpmcliHashesCurrent
Definition: rpminstall.c:65
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:30
const char * rpmgiHdrPath(rpmgi gi)
Return current header path.
Definition: rpmgi.c:840
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:9
Access RPM indices using Berkeley DB interface(s).
#define D_(Text)
Definition: system.h:485
int rpmcliInstallSuggests(rpmts ts)
Report packages(if any) that satisfy unresolved dependencies.
Definition: rpminstall.c:323
unsigned int rpmmiCount(rpmmi mi)
Return number of elements in rpm database iterator.
Definition: rpmdb.c:1759
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&#39;s not.
int rpmExpandNumeric(const char *arg)
Return macro expansion as a numeric value.
Definition: macro.c:3191
#define FTS_ERR
Definition: fts.h:135
void rpmtsEmpty(rpmts ts)
Re-create an empty transaction set.
Definition: rpmts.c:623
int rpmVersionCompare(Header A, Header B)
Definition: rpmevr.c:419
tsmStage rpmtsSetGoal(rpmts ts, tsmStage goal)
Set goal of transaction set.
Definition: rpmts.c:1425
void rpmtsClean(rpmts ts)
Free memory needed only for dependency checks and ordering.
Definition: rpmts.c:596
#define FTS_SKIP
Definition: fts.h:152