rpm  4.5
rpminstall.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmcli.h>
8 
9 #include "rpmdb.h"
10 #ifdef NOTYET
11 #include "rpmds.h" /* XXX ts->suggests, +foo -foo =foo args */
12 #endif
13 
14 #include "rpmte.h" /* XXX rpmtsPrint() */
15 #define _RPMTS_INTERNAL /* XXX ts->goal, ts->suggests */
16 #include "rpmts.h"
17 
18 #include "manifest.h"
19 #include "misc.h" /* XXX rpmGlob() */
20 #include "rpmgi.h" /* XXX rpmgiEscapeSpaces */
21 #include "debug.h"
22 
23 /*@access rpmts @*/ /* XXX ts->goal */
24 
25 /*@unchecked@*/
27 /*@unchecked@*/
29 /*@unchecked@*/
31 /*@unchecked@*/
32 unsigned long long rpmcliProgressCurrent = 0;
33 /*@unchecked@*/
34 unsigned long long rpmcliProgressTotal = 0;
35 
42 static void printHash(const unsigned long long amount, const unsigned long long total)
43  /*@globals rpmcliHashesCurrent, rpmcliHashesTotal,
44  rpmcliProgressCurrent, fileSystem @*/
45  /*@modifies rpmcliHashesCurrent, rpmcliHashesTotal,
46  rpmcliProgressCurrent, fileSystem @*/
47 {
48  int hashesNeeded;
49 
50  rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
51 
53 /*@+relaxtypes@*/
54  float pct = (total ? (((float) amount) / total) : 1.0);
55  hashesNeeded = (rpmcliHashesTotal * pct) + 0.5;
56 /*@=relaxtypes@*/
57  while (hashesNeeded > rpmcliHashesCurrent) {
58  if (isatty (STDOUT_FILENO)) {
59  int i;
60  for (i = 0; i < rpmcliHashesCurrent; i++)
61  (void) putchar ('#');
62  for (; i < rpmcliHashesTotal; i++)
63  (void) putchar (' ');
64  fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
65  for (i = 0; i < (rpmcliHashesTotal + 6); i++)
66  (void) putchar ('\b');
67  } else
68  fprintf(stdout, "#");
69 
71  }
72  (void) fflush(stdout);
73 
75  int i;
77  if (isatty(STDOUT_FILENO)) {
78  for (i = 1; i < rpmcliHashesCurrent; i++)
79  (void) putchar ('#');
80 /*@+relaxtypes@*/
81  pct = (rpmcliProgressTotal
83  : 1);
84 /*@=relaxtypes@*/
85  fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
86  }
87  fprintf(stdout, "\n");
88  }
89  (void) fflush(stdout);
90  }
91 }
92 
93 void * rpmShowProgress(/*@null@*/ const void * arg,
94  const rpmCallbackType what,
95  const unsigned long long amount,
96  const unsigned long long total,
97  /*@null@*/ fnpyKey key,
98  /*@null@*/ void * data)
99  /*@globals rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
100  fileSystem @*/
101  /*@modifies rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
102  fileSystem @*/
103 {
104 /*@-abstract -castexpose @*/
105  Header h = (Header) arg;
106 /*@=abstract =castexpose @*/
107  char * s;
108  int flags = (int) ((long)data);
109  void * rc = NULL;
110 /*@-abstract -assignexpose @*/
111  const char * filename = (const char *)key;
112 /*@=abstract =assignexpose @*/
113  static FD_t fd = NULL;
114  int xx;
115 
116  switch (what) {
118 /*@-boundsread@*/
119  if (filename == NULL || filename[0] == '\0')
120  return NULL;
121 /*@=boundsread@*/
122  fd = Fopen(filename, "r");
123  /*@-type@*/ /* FIX: still necessary? */
124  if (fd == NULL || Ferror(fd)) {
125  rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), filename,
126  Fstrerror(fd));
127  if (fd != NULL) {
128  xx = Fclose(fd);
129  fd = NULL;
130  }
131  } else {
132  long oldfl;
133  fd = fdLink(fd, "persist (showProgress)");
134  oldfl=Fcntl(fd, F_GETFD, 0);
135  if(oldfl >= 0) {
136  oldfl |= FD_CLOEXEC; /* scripts shouldn't inherit rpm file descriptor */
137  Fcntl(fd, F_SETFD, (void*)oldfl);
138  }
139  }
140  /*@=type@*/
141 /*@+voidabstract@*/
142  return (void *)fd;
143 /*@=voidabstract@*/
144  /*@notreached@*/ break;
145 
147  /*@-type@*/ /* FIX: still necessary? */
148  fd = fdFree(fd, "persist (showProgress)");
149  /*@=type@*/
150  if (fd != NULL) {
151  xx = Fclose(fd);
152  fd = NULL;
153  }
154  break;
155 
158  if (h == NULL || !(flags & INSTALL_LABEL))
159  break;
160  /* @todo Remove headerSprintf() on a progress callback. */
161  if (flags & INSTALL_HASH) {
162  s = headerSprintf(h, "%{NAME}",
164  if (isatty (STDOUT_FILENO))
165  fprintf(stdout, "%4d:%-23.23s", (int)rpmcliProgressCurrent + 1, s);
166  else
167  fprintf(stdout, "%-28.28s", s);
168  (void) fflush(stdout);
169  s = _free(s);
170  } else {
171  s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
173  fprintf(stdout, "%s\n", s);
174  (void) fflush(stdout);
175  s = _free(s);
176  }
177  break;
178 
181 /*@+relaxtypes@*/
182  if (flags & INSTALL_PERCENT)
183  fprintf(stdout, "%%%% %f\n", (double) (total
184  ? ((((float) amount) / total) * 100)
185  : 100.0));
186  else if (flags & INSTALL_HASH)
187  printHash(amount, total);
188 /*@=relaxtypes@*/
189  (void) fflush(stdout);
190  break;
191 
196  if (!(flags & INSTALL_LABEL))
197  break;
198  if (flags & INSTALL_HASH)
199  fprintf(stdout, "%-28s", _("Preparing..."));
200  else
201  fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
202  (void) fflush(stdout);
203  break;
204 
206  if (flags & INSTALL_HASH)
207  printHash(1, 1); /* Fixes "preparing..." progress bar */
210  break;
211 
214  rpmcliProgressTotal = total;
216  if (!(flags & INSTALL_LABEL))
217  break;
218  if (flags & INSTALL_HASH)
219  fprintf(stdout, "%-28s\n", _("Repackaging..."));
220  else
221  fprintf(stdout, "%s\n", _("Repackaging erased files..."));
222  (void) fflush(stdout);
223  break;
224 
226  if (amount && (flags & INSTALL_HASH))
227  printHash(1, 1); /* Fixes "preparing..." progress bar */
228  break;
229 
231  rpmcliProgressTotal = total;
232  rpmcliProgressCurrent = total;
233  if (flags & INSTALL_HASH)
234  printHash(1, 1); /* Fixes "preparing..." progress bar */
237  if (!(flags & INSTALL_LABEL))
238  break;
239  if (flags & INSTALL_HASH)
240  fprintf(stdout, "%-28s\n", _("Upgrading..."));
241  else
242  fprintf(stdout, "%s\n", _("Upgrading packages..."));
243  (void) fflush(stdout);
244  break;
245 
247  break;
249  break;
251  break;
253  break;
255  break;
256  case RPMCALLBACK_UNKNOWN:
257  default:
258  break;
259  }
260 
261  return rc;
262 }
263 
264 typedef /*@only@*/ /*@null@*/ const char * str_t;
265 
266 struct rpmEIU {
270  int numPkgs;
271 /*@only@*/
273 /*@dependent@*/ /*@null@*/
275 /*@only@*/
276  char * pkgState;
277  int prevx;
278  int pkgx;
279  int numRPMS;
280  int numSRPMS;
281 /*@only@*/ /*@null@*/
283  int isSource;
284  int argc;
285 /*@only@*/ /*@null@*/
287 /*@dependent@*/
290 };
291 
293 /*@-bounds@*/
294 int rpmInstall(rpmts ts, QVA_t ia, const char ** fileArgv)
295 {
296  struct rpmEIU * eiu = memset(alloca(sizeof(*eiu)), 0, sizeof(*eiu));
297  rpmps ps;
298  rpmprobFilterFlags probFilter;
300 /*@only@*/ /*@null@*/ const char * fileURL = NULL;
301  int stopInstall = 0;
302  const char ** av = NULL;
303  const char *fn;
304  rpmVSFlags vsflags, ovsflags, tvsflags;
305  int ac = 0;
306  int rc;
307  int xx;
308  int i;
309 
310  if (fileArgv == NULL) goto exit;
311 
312  ts->goal = TSM_INSTALL;
314 
315  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
317 
318  /* Initialize security context patterns (if not already done). */
319  if (!(ia->transFlags & RPMTRANS_FLAG_NOCONTEXTS)) {
320  const char *fn = rpmGetPath("%{?_install_file_context_path}", NULL);
321  if (fn != NULL && *fn != '\0')
322  xx = matchpathcon_init(fn);
323  fn = _free(fn);
324  }
325  (void) rpmtsSetFlags(ts, ia->transFlags);
326  (void) rpmtsSetDFlags(ts, ia->depFlags);
327 
328  /* Display and set autorollback goal. */
329  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
330  if (ia->arbtid) {
331  time_t ttid = (time_t)ia->arbtid;
332  rpmMessage(RPMMESS_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
333  ctime(&ttid), ia->arbtid);
334  rpmtsSetARBGoal(ts, ia->arbtid);
335  }
336  }
337 
338  probFilter = ia->probFilter;
339  relocations = ia->relocations;
340 
342  vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
343  else
344  vsflags = rpmExpandNumeric("%{?_vsflags_install}");
345  if (ia->qva_flags & VERIFY_DIGEST)
346  vsflags |= _RPMVSF_NODIGESTS;
347  if (ia->qva_flags & VERIFY_SIGNATURE)
348  vsflags |= _RPMVSF_NOSIGNATURES;
349  if (ia->qva_flags & VERIFY_HDRCHK)
350  vsflags |= RPMVSF_NOHDRCHK;
351  ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD));
352 
353  { int notifyFlags;
354  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
355  xx = rpmtsSetNotifyCallback(ts,
356  rpmShowProgress, (void *) ((long)notifyFlags));
357  }
358 
359  if ((eiu->relocations = relocations) != NULL) {
360  while (eiu->relocations->oldPath)
361  eiu->relocations++;
362  if (eiu->relocations->newPath == NULL)
363  eiu->relocations = NULL;
364  }
365 
366  /* Build fully globbed list of arguments in argv[argc]. */
367  /*@-branchstate@*/
368  /*@-temptrans@*/
369  for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) {
370  /*@=temptrans@*/
371  av = _free(av); ac = 0;
372  fn = rpmgiEscapeSpaces(*eiu->fnp);
373  rc = rpmGlob(fn, &ac, &av);
374  fn = _free(fn);
375  if (rc || ac == 0) {
376  rpmError(RPMERR_OPEN, _("File not found by glob: %s\n"), *eiu->fnp);
377  continue;
378  }
379 
380  eiu->argv = xrealloc(eiu->argv, (eiu->argc+ac+1) * sizeof(*eiu->argv));
381  memcpy(eiu->argv+eiu->argc, av, ac * sizeof(*av));
382  eiu->argc += ac;
383  eiu->argv[eiu->argc] = NULL;
384  }
385  /*@=branchstate@*/
386  av = _free(av); ac = 0;
387 
388 restart:
389  /* Allocate sufficient storage for next set of args. */
390  if (eiu->pkgx >= eiu->numPkgs) {
391  eiu->numPkgs = eiu->pkgx + eiu->argc;
392  eiu->pkgURL = xrealloc(eiu->pkgURL,
393  (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL));
394  memset(eiu->pkgURL + eiu->pkgx, 0,
395  ((eiu->argc + 1) * sizeof(*eiu->pkgURL)));
396  eiu->pkgState = xrealloc(eiu->pkgState,
397  (eiu->numPkgs + 1) * sizeof(*eiu->pkgState));
398  memset(eiu->pkgState + eiu->pkgx, 0,
399  ((eiu->argc + 1) * sizeof(*eiu->pkgState)));
400  }
401 
402  /* Retrieve next set of args, cache on local storage. */
403  for (i = 0; i < eiu->argc; i++) {
404  fileURL = _free(fileURL);
405  fileURL = eiu->argv[i];
406  eiu->argv[i] = NULL;
407 
408 #ifdef NOTYET
409 if (fileURL[0] == '=') {
410  rpmds this = rpmdsSingle(RPMTAG_REQUIRENAME, fileURL+1, NULL, 0);
411 
412  xx = rpmtsSolve(ts, this, NULL);
413  if (ts->suggests && ts->nsuggests > 0) {
414  fileURL = _free(fileURL);
415  fileURL = ts->suggests[0];
416  ts->suggests[0] = NULL;
417  while (ts->nsuggests-- > 0) {
418  if (ts->suggests[ts->nsuggests] == NULL)
419  continue;
420  ts->suggests[ts->nsuggests] = _free(ts->suggests[ts->nsuggests]);
421  }
422  ts->suggests = _free(ts->suggests);
423  rpmMessage(RPMMESS_DEBUG, D_("Adding goal: %s\n"), fileURL);
424  eiu->pkgURL[eiu->pkgx] = fileURL;
425  fileURL = NULL;
426  eiu->pkgx++;
427  }
428  this = rpmdsFree(this);
429 } else
430 #endif
431 
432  switch (urlIsURL(fileURL)) {
433  case URL_IS_HTTPS:
434  case URL_IS_HTTP:
435  case URL_IS_FTP:
436  { const char *tfn;
437 
438  if (rpmIsVerbose())
439  fprintf(stdout, _("Retrieving %s\n"), fileURL);
440 
441  { char tfnbuf[64];
442  const char * rootDir = rpmtsRootDir(ts);
443  if (!(rootDir && * rootDir))
444  rootDir = "";
445  strcpy(tfnbuf, "rpm-xfer.XXXXXX");
446  (void) mktemp(tfnbuf);
447  tfn = rpmGenPath(rootDir, "%{_tmppath}/", tfnbuf);
448  }
449 
450  /* XXX undefined %{name}/%{version}/%{release} here */
451  /* XXX %{_tmpdir} does not exist */
452  rpmMessage(RPMMESS_DEBUG, D_(" ... as %s\n"), tfn);
453  rc = urlGetFile(fileURL, tfn);
454  if (rc < 0) {
456  _("skipping %s - transfer failed - %s\n"),
457  fileURL, ftpStrerror(rc));
458  eiu->numFailed++;
459  eiu->pkgURL[eiu->pkgx] = NULL;
460  tfn = _free(tfn);
461  /*@switchbreak@*/ break;
462  }
463  eiu->pkgState[eiu->pkgx] = 1;
464  eiu->pkgURL[eiu->pkgx] = tfn;
465  eiu->pkgx++;
466  } /*@switchbreak@*/ break;
467  case URL_IS_PATH:
468  case URL_IS_DASH: /* WRONG WRONG WRONG */
469  case URL_IS_HKP: /* WRONG WRONG WRONG */
470  default:
471  eiu->pkgURL[eiu->pkgx] = fileURL;
472  fileURL = NULL;
473  eiu->pkgx++;
474  /*@switchbreak@*/ break;
475  }
476  }
477  fileURL = _free(fileURL);
478 
479  if (eiu->numFailed) goto exit;
480 
481  /* Continue processing file arguments, building transaction set. */
482  for (eiu->fnp = eiu->pkgURL+eiu->prevx;
483  *eiu->fnp != NULL;
484  eiu->fnp++, eiu->prevx++)
485  {
486  const char * fileName;
487 
488  rpmMessage(RPMMESS_DEBUG, "============== %s\n", *eiu->fnp);
489  (void) urlPath(*eiu->fnp, &fileName);
490 
491  /* Try to read the header from a package file. */
492  eiu->fd = Fopen(*eiu->fnp, "r");
493  if (eiu->fd == NULL || Ferror(eiu->fd)) {
494  rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
495  Fstrerror(eiu->fd));
496  if (eiu->fd != NULL) {
497  xx = Fclose(eiu->fd);
498  eiu->fd = NULL;
499  }
500  eiu->numFailed++; *eiu->fnp = NULL;
501  continue;
502  }
503 
504  /* Read the header, verifying signatures (if present). */
505  tvsflags = rpmtsSetVSFlags(ts, vsflags);
506  eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h);
507  tvsflags = rpmtsSetVSFlags(ts, tvsflags);
508  xx = Fclose(eiu->fd);
509  eiu->fd = NULL;
510 
511  switch (eiu->rpmrc) {
512  case RPMRC_FAIL:
513  rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *eiu->fnp);
514  eiu->numFailed++; *eiu->fnp = NULL;
515  continue;
516  /*@notreached@*/ /*@switchbreak@*/ break;
517  case RPMRC_NOTFOUND:
518  goto maybe_manifest;
519  /*@notreached@*/ /*@switchbreak@*/ break;
520  case RPMRC_NOTTRUSTED:
521  case RPMRC_NOKEY:
522  case RPMRC_OK:
523  default:
524  /*@switchbreak@*/ break;
525  }
526 
527  eiu->isSource = (headerIsEntry(eiu->h, RPMTAG_SOURCERPM) == 0);
528 
529  if (eiu->isSource) {
530  rpmMessage(RPMMESS_DEBUG, D_("\tadded source package [%d]\n"),
531  eiu->numSRPMS);
532  eiu->sourceURL = xrealloc(eiu->sourceURL,
533  (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL));
534  eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp;
535  *eiu->fnp = NULL;
536  eiu->numSRPMS++;
537  eiu->sourceURL[eiu->numSRPMS] = NULL;
538  continue;
539  }
540 
541  if (eiu->relocations) {
542  const char ** paths;
543  int pft;
544  int c;
545 
546  if (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft, &paths, &c)
547  && c == 1)
548  {
549  eiu->relocations->oldPath = xstrdup(paths[0]);
550  paths = headerFreeData(paths, pft);
551  } else {
552  const char * name;
553  xx = headerNVR(eiu->h, &name, NULL, NULL);
555  _("package %s is not relocatable\n"), name);
556  eiu->numFailed++;
557  goto exit;
558  /*@notreached@*/
559  }
560  }
561 
562  /* On --freshen, verify package is installed and newer */
565  const char * name;
566  Header oldH;
567  int count;
568 
569  xx = headerNVR(eiu->h, &name, NULL, NULL);
570  mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0);
571  count = rpmdbGetIteratorCount(mi);
572  while ((oldH = rpmdbNextIterator(mi)) != NULL) {
573  if (rpmVersionCompare(oldH, eiu->h) < 0)
574  /*@innercontinue@*/ continue;
575  /* same or newer package already installed */
576  count = 0;
577  /*@innerbreak@*/ break;
578  }
579  mi = rpmdbFreeIterator(mi);
580  if (count == 0) {
581  eiu->h = headerFree(eiu->h);
582  continue;
583  }
584  /* Package is newer than those currently installed. */
585  }
586 
587  /*@-abstract@*/
588  rc = rpmtsAddInstallElement(ts, eiu->h, (fnpyKey)fileName,
590  relocations);
591  /*@=abstract@*/
592 
593  /* XXX reference held by transaction set */
594  eiu->h = headerFree(eiu->h);
595  if (eiu->relocations)
597 
598  switch(rc) {
599  case 0:
600  rpmMessage(RPMMESS_DEBUG, D_("\tadded binary package [%d]\n"),
601  eiu->numRPMS);
602  eiu->numRPMS++;
603  /*@switchbreak@*/ break;
604  case 1:
606  _("package file %s was skipped\n"), *eiu->fnp);
607  /*@switchbreak@*/ break;
608  case 2:
610  _("file %s requires a newer version of RPM\n"),
611  *eiu->fnp);
612  eiu->numFailed++;
613  goto exit;
614  /*@notreached@*/ /*@switchbreak@*/ break;
615  }
616 
617  continue;
618 
619 maybe_manifest:
620  /* Try to read a package manifest. */
621  eiu->fd = Fopen(*eiu->fnp, "r.fpio");
622  if (eiu->fd == NULL || Ferror(eiu->fd)) {
623  rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
624  Fstrerror(eiu->fd));
625  if (eiu->fd != NULL) {
626  xx = Fclose(eiu->fd);
627  eiu->fd = NULL;
628  }
629  eiu->numFailed++; *eiu->fnp = NULL;
630  break;
631  }
632 
633  /* Read list of packages from manifest. */
634 /*@-nullstate@*/ /* FIX: *eiu->argv can be NULL */
635  rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv);
636 /*@=nullstate@*/
637  if (rc != RPMRC_OK)
638  rpmError(RPMERR_MANIFEST, _("%s: not an rpm package (or package manifest): %s\n"),
639  *eiu->fnp, Fstrerror(eiu->fd));
640  xx = Fclose(eiu->fd);
641  eiu->fd = NULL;
642 
643  /* If successful, restart the query loop. */
644  if (rc == RPMRC_OK) {
645  eiu->prevx++;
646  goto restart;
647  }
648 
649  eiu->numFailed++; *eiu->fnp = NULL;
650  break;
651  }
652 
653  rpmMessage(RPMMESS_DEBUG, D_("found %d source and %d binary packages\n"),
654  eiu->numSRPMS, eiu->numRPMS);
655 
656  if (eiu->numFailed) goto exit;
657 
658  if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NODEPS)) {
659 
660  if (rpmtsCheck(ts)) {
661  eiu->numFailed = eiu->numPkgs;
662  stopInstall = 1;
663  }
664 
665  ps = rpmtsProblems(ts);
666  if (!stopInstall && rpmpsNumProblems(ps) > 0) {
667  rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
668  rpmpsPrint(NULL, ps);
669  eiu->numFailed = eiu->numPkgs;
670  stopInstall = 1;
671 
672  /*@-branchstate@*/
673  if (ts->suggests != NULL && ts->nsuggests > 0) {
674  rpmMessage(RPMMESS_NORMAL, _(" Suggested resolutions:\n"));
675  for (i = 0; i < ts->nsuggests; i++) {
676  const char * str = ts->suggests[i];
677 
678  if (str == NULL)
679  break;
680 
681  rpmMessage(RPMMESS_NORMAL, "\t%s\n", str);
682 
683  ts->suggests[i] = NULL;
684  str = _free(str);
685  }
686  ts->suggests = _free(ts->suggests);
687  }
688  /*@=branchstate@*/
689  }
690  ps = rpmpsFree(ps);
691  }
692 
693  if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
694  if (rpmtsOrder(ts)) {
695  eiu->numFailed = eiu->numPkgs;
696  stopInstall = 1;
697  }
698  }
699 
700  if (eiu->numRPMS && !stopInstall) {
701 
703 
704  rpmMessage(RPMMESS_DEBUG, D_("installing binary packages\n"));
705 
706  /* Drop added/available package indices and dependency sets. */
707  rpmtsClean(ts);
708 
709  rc = rpmtsRun(ts, NULL, probFilter);
710  ps = rpmtsProblems(ts);
711 
712  if (rc < 0) {
713  eiu->numFailed += eiu->numRPMS;
714  } else if (rc > 0) {
715  eiu->numFailed += rc;
716  if (rpmpsNumProblems(ps) > 0)
717  rpmpsPrint(stderr, ps);
718  }
719  ps = rpmpsFree(ps);
720  }
721 
722  if (eiu->numSRPMS && !stopInstall) {
723  if (eiu->sourceURL != NULL)
724  for (i = 0; i < eiu->numSRPMS; i++) {
725  if (eiu->sourceURL[i] == NULL) continue;
726  eiu->fd = Fopen(eiu->sourceURL[i], "r");
727  if (eiu->fd == NULL || Ferror(eiu->fd)) {
728  rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
729  eiu->sourceURL[i], Fstrerror(eiu->fd));
730  if (eiu->fd != NULL) {
731  xx = Fclose(eiu->fd);
732  eiu->fd = NULL;
733  }
734  continue;
735  }
736 
737  if (!(rpmtsFlags(ts) & RPMTRANS_FLAG_TEST)) {
738  eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL, NULL);
739  if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++;
740  }
741 
742  xx = Fclose(eiu->fd);
743  eiu->fd = NULL;
744  }
745  }
746 
747 exit:
748  if (eiu->pkgURL != NULL)
749  for (i = 0; i < eiu->numPkgs; i++) {
750  if (eiu->pkgURL[i] == NULL) continue;
751  if (eiu->pkgState[i] == 1)
752  (void) Unlink(eiu->pkgURL[i]);
753  eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
754  }
755  eiu->pkgState = _free(eiu->pkgState);
756  eiu->pkgURL = _free(eiu->pkgURL);
757  eiu->argv = _free(eiu->argv);
758 
759  rpmtsEmpty(ts);
760 
761  return eiu->numFailed;
762 }
763 /*@=bounds@*/
764 
765 int rpmErase(rpmts ts, QVA_t ia, const char ** argv)
766 {
767  int count;
768  const char ** arg;
769  int numFailed = 0;
770  int stopUninstall = 0;
771  int numPackages = 0;
772  rpmVSFlags vsflags, ovsflags;
773  rpmps ps;
774 
775  if (argv == NULL) return 0;
776 
777  vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
778  if (ia->qva_flags & VERIFY_DIGEST)
779  vsflags |= _RPMVSF_NODIGESTS;
780  if (ia->qva_flags & VERIFY_SIGNATURE)
781  vsflags |= _RPMVSF_NOSIGNATURES;
782  if (ia->qva_flags & VERIFY_HDRCHK)
783  vsflags |= RPMVSF_NOHDRCHK;
784  ovsflags = rpmtsSetVSFlags(ts, vsflags);
785 
786  if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
788 
789  (void) rpmtsSetFlags(ts, ia->transFlags);
790  (void) rpmtsSetDFlags(ts, ia->depFlags);
791 
792  /* Display and set autorollback goal. */
793  if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
794  if (ia->arbtid) {
795  time_t ttid = (time_t)ia->arbtid;
796  rpmMessage(RPMMESS_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
797  ctime(&ttid), ia->arbtid);
798  rpmtsSetARBGoal(ts, ia->arbtid);
799  }
800  }
801 
802 #ifdef NOTYET /* XXX no callbacks on erase yet */
803  { int notifyFlags;
804  notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
805  xx = rpmtsSetNotifyCallback(ts,
806  rpmShowProgress, (void *) ((long)notifyFlags));
807  }
808 #endif
809 
810  ts->goal = TSM_ERASE;
811 
812  for (arg = argv; *arg; arg++) {
814 
815  /* XXX HACK to get rpmdbFindByLabel out of the API */
816  mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
817  if (mi == NULL) {
818  rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
819  numFailed++;
820  } else {
821  Header h; /* XXX iterator owns the reference */
822  count = 0;
823  while ((h = rpmdbNextIterator(mi)) != NULL) {
824  unsigned int recOffset = rpmdbGetIteratorOffset(mi);
825 
826  if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) {
827  rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
828  *arg);
829  numFailed++;
830  /*@innerbreak@*/ break;
831  }
832  if (recOffset) {
833  (void) rpmtsAddEraseElement(ts, h, recOffset);
834  numPackages++;
835  }
836  }
837  }
838  mi = rpmdbFreeIterator(mi);
839  }
840 
841  if (numFailed) goto exit;
842 
843  if (!(ia->installInterfaceFlags & INSTALL_NODEPS)) {
844 
845  if (rpmtsCheck(ts)) {
846  numFailed = numPackages;
847  stopUninstall = 1;
848  }
849 
850  ps = rpmtsProblems(ts);
851  if (!stopUninstall && rpmpsNumProblems(ps) > 0) {
852  rpmMessage(RPMMESS_ERROR, _("Failed dependencies:\n"));
853  rpmpsPrint(NULL, ps);
854  numFailed += numPackages;
855  stopUninstall = 1;
856  }
857  ps = rpmpsFree(ps);
858  }
859 
860  if (!stopUninstall && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
861  if (rpmtsOrder(ts)) {
862  numFailed += numPackages;
863  stopUninstall = 1;
864  }
865  }
866 
867  if (numPackages > 0 && !stopUninstall) {
868 
869  /* Drop added/available package indices and dependency sets. */
870  rpmtsClean(ts);
871 
872  numPackages = rpmtsRun(ts, NULL, 0);
873  ps = rpmtsProblems(ts);
874  if (rpmpsNumProblems(ps) > 0)
875  rpmpsPrint(NULL, ps);
876  numFailed += numPackages;
877  stopUninstall = 1;
878  ps = rpmpsFree(ps);
879  }
880 
881 exit:
882  rpmtsEmpty(ts);
883 
884  return numFailed;
885 }
886 
887 int rpmInstallSource(rpmts ts, const char * arg,
888  const char ** specFilePtr, const char ** cookie)
889 {
890  FD_t fd;
891  int rc;
892 
893 
894  fd = Fopen(arg, "r");
895  if (fd == NULL || Ferror(fd)) {
896  rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
897  if (fd != NULL) (void) Fclose(fd);
898  return 1;
899  }
900 
901  if (rpmIsVerbose())
902  fprintf(stdout, _("Installing %s\n"), arg);
903 
904  {
905  rpmVSFlags ovsflags =
907  rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
908  rc = (rpmrc == RPMRC_OK ? 0 : 1);
909  ovsflags = rpmtsSetVSFlags(ts, ovsflags);
910  }
911  if (rc != 0) {
912  rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
913  /*@-unqualifiedtrans@*/
914  if (specFilePtr && *specFilePtr)
915  *specFilePtr = _free(*specFilePtr);
916  if (cookie && *cookie)
917  *cookie = _free(*cookie);
918  /*@=unqualifiedtrans@*/
919  }
920 
921  (void) Fclose(fd);
922 
923  return rc;
924 }