rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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 #include <rpmevr.h>
13 #include "rpmdb.h"
14 #ifdef NOTYET
15 #include "rpmds.h" /* XXX ts->suggests, +foo -foo =foo args */
16 #endif
17
18 #include "rpmte.h" /* XXX rpmtsPrint() */
19 #define _RPMTS_INTERNAL /* XXX ts->suggests */
20 #include <rpmts.h>
21
22 #include "manifest.h"
23 #define _RPMGI_INTERNAL /* XXX "+bing" args need gi->h. */
24 #include "rpmgi.h"
25
26 #include <rpmlib.h>
27
28 #include <rpmcli.h>
29 #define _RPMROLLBACK_INTERNAL
30 #include <rpmrollback.h>
31
32 #include "debug.h"
33
34 /*@access FD_t @*/ /* XXX void * arg */
35 /*@access rpmts @*/ /* XXX ts->suggests */
36 /*@access rpmgi @*/ /* XXX gi->h */
37 /*@access fnpyKey @*/ /* XXX cast */
38
39 /*@unchecked@*/
40 int rpmcliPackagesTotal = 0;
41 /*@unchecked@*/
42 int rpmcliHashesCurrent = 0;
43 /*@unchecked@*/
44 int rpmcliHashesTotal = 0;
45 /*@unchecked@*/
46 rpmuint64_t rpmcliProgressCurrent = 0;
47 /*@unchecked@*/
48 rpmuint64_t rpmcliProgressTotal = 0;
49
56 static void printHash(const rpmuint64_t amount, const rpmuint64_t total)
57 /*@globals rpmcliHashesCurrent, rpmcliHashesTotal,
58 rpmcliProgressCurrent, fileSystem @*/
59 /*@modifies rpmcliHashesCurrent, rpmcliHashesTotal,
60 rpmcliProgressCurrent, fileSystem @*/
61 {
62 int hashesNeeded;
63
64 rpmcliHashesTotal = (isatty (STDOUT_FILENO) ? 44 : 50);
65
66 if (rpmcliHashesCurrent != rpmcliHashesTotal) {
67 float pct = (float) (total ? (((float) amount) / total) : 1);
68 hashesNeeded = (int)((rpmcliHashesTotal * pct) + 0.5);
69 while (hashesNeeded > rpmcliHashesCurrent) {
70 if (isatty (STDOUT_FILENO)) {
71 int i;
72 for (i = 0; i < rpmcliHashesCurrent; i++)
73 (void) putchar ('#');
74 for (; i < rpmcliHashesTotal; i++)
75 (void) putchar (' ');
76 fprintf(stdout, "(%3d%%)", (int)((100 * pct) + 0.5));
77 for (i = 0; i < (rpmcliHashesTotal + 6); i++)
78 (void) putchar ('\b');
79 } else
80 fprintf(stdout, "#");
81
82 rpmcliHashesCurrent++;
83 }
84 (void) fflush(stdout);
85
86 if (rpmcliHashesCurrent == rpmcliHashesTotal) {
87 int i;
88 rpmcliProgressCurrent++;
89 if (isatty(STDOUT_FILENO)) {
90 for (i = 1; i < rpmcliHashesCurrent; i++)
91 (void) putchar ('#');
92 pct = (float) (rpmcliProgressTotal
93 ? (((float) rpmcliProgressCurrent) / rpmcliProgressTotal)
94 : 1);
95 fprintf(stdout, " [%3d%%]", (int)((100 * pct) + 0.5));
96 }
97 fprintf(stdout, "\n");
98 }
99 (void) fflush(stdout);
100 }
101 }
102
103 void * rpmShowProgress(/*@null@*/ const void * arg,
104 const rpmCallbackType what,
105 const rpmuint64_t amount,
106 const rpmuint64_t total,
107 /*@null@*/ fnpyKey key,
108 /*@null@*/ void * data)
109 /*@globals rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
110 rpmGlobalMacroContext, fileSystem @*/
111 /*@modifies rpmcliHashesCurrent, rpmcliProgressCurrent, rpmcliProgressTotal,
112 rpmGlobalMacroContext, fileSystem @*/
113 {
114 /*@-abstract -castexpose @*/
115 Header h = (Header) arg;
116 /*@=abstract =castexpose @*/
117 const char * s;
118 int flags = (int) ((long)data);
119 void * rc = NULL;
120 /*@-abstract -assignexpose @*/
121 const char * filename = (const char *)key;
122 /*@=abstract =assignexpose @*/
123 static FD_t fd = NULL;
124 int xx;
125
126 switch (what) {
127 case RPMCALLBACK_INST_OPEN_FILE:
128 if (filename == NULL || filename[0] == '\0')
129 return NULL;
130 fd = Fopen(filename, "r%{?_rpmgio}");
131
132 /* XXX Retry once to handle http:// server timeout reopen's. */
133 if (Ferror(fd)) {
134 int ut = urlPath(filename, NULL);
135 if (ut == URL_IS_HTTP || ut == URL_IS_HTTPS) {
136 /* XXX HACK: Fclose(fd) no workie here. */
137 fd = Fopen(filename, "r%{?_rpmgio}");
138 }
139 }
140
141 /*@-type@*/ /* FIX: still necessary? */
142 if (fd == NULL || Ferror(fd)) {
143 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), filename,
144 Fstrerror(fd));
145 if (fd != NULL) {
146 xx = Fclose(fd);
147 fd = NULL;
148 }
149 } else
150 fd = fdLink(fd, "persist (showProgress)");
151 /*@=type@*/
152 /*@+voidabstract@*/
153 return (void *)fd;
154 /*@=voidabstract@*/
155 /*@notreached@*/ break;
156
157 case RPMCALLBACK_INST_CLOSE_FILE:
158 /*@-type@*/ /* FIX: still necessary? */
159 fd = fdFree(fd, "persist (showProgress)");
160 /*@=type@*/
161 if (fd != NULL) {
162 xx = Fclose(fd);
163 fd = NULL;
164 }
165 break;
166
167 case RPMCALLBACK_INST_START:
168 rpmcliHashesCurrent = 0;
169 if (h == NULL || !(flags & INSTALL_LABEL))
170 break;
171 /* @todo Remove headerSprintf() on a progress callback. */
172 if (flags & INSTALL_HASH) {
173 s = headerSprintf(h, "%{NAME}",
174 NULL, rpmHeaderFormats, NULL);
175 if (isatty (STDOUT_FILENO))
176 fprintf(stdout, "%4d:%-23.23s", (int)rpmcliProgressCurrent + 1, s);
177 else
178 fprintf(stdout, "%-28.28s", s);
179 (void) fflush(stdout);
180 s = _free(s);
181 } else {
182 char * t = rpmExpand("%{?___NVRA}%{!?___NVRA:%%{NAME}-%%{VERSION}-%%{RELEASE}}", NULL);
183 s = headerSprintf(h, t, NULL, rpmHeaderFormats, NULL);
184 fprintf(stdout, "%s\n", s);
185 (void) fflush(stdout);
186 s = _free(s);
187 t = _free(t);
188 }
189 break;
190
191 case RPMCALLBACK_TRANS_PROGRESS:
192 case RPMCALLBACK_INST_PROGRESS:
193 /*@+relaxtypes@*/
194 if (flags & INSTALL_PERCENT)
195 fprintf(stdout, "%%%% %f\n", (double) (total
196 ? ((((float) amount) / total) * 100)
197 : 100.0));
198 else if (flags & INSTALL_HASH)
199 printHash(amount, total);
200 /*@=relaxtypes@*/
201 (void) fflush(stdout);
202 break;
203
204 case RPMCALLBACK_TRANS_START:
205 rpmcliHashesCurrent = 0;
206 rpmcliProgressTotal = 1;
207 rpmcliProgressCurrent = 0;
208 if (!(flags & INSTALL_LABEL))
209 break;
210 if (flags & INSTALL_HASH)
211 fprintf(stdout, "%-28s", _("Preparing..."));
212 else
213 fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
214 (void) fflush(stdout);
215 break;
216
217 case RPMCALLBACK_TRANS_STOP:
218 if (flags & INSTALL_HASH)
219 printHash(1, 1); /* Fixes "preparing..." progress bar */
220 rpmcliProgressTotal = rpmcliPackagesTotal;
221 rpmcliProgressCurrent = 0;
222 break;
223
224 case RPMCALLBACK_REPACKAGE_START:
225 rpmcliHashesCurrent = 0;
226 rpmcliProgressTotal = total;
227 rpmcliProgressCurrent = 0;
228 if (!(flags & INSTALL_LABEL))
229 break;
230 if (flags & INSTALL_HASH)
231 fprintf(stdout, "%-28s\n", _("Repackaging..."));
232 else
233 fprintf(stdout, "%s\n", _("Repackaging erased files..."));
234 (void) fflush(stdout);
235 break;
236
237 case RPMCALLBACK_REPACKAGE_PROGRESS:
238 if (amount && (flags & INSTALL_HASH))
239 printHash(1, 1); /* Fixes "preparing..." progress bar */
240 break;
241
242 case RPMCALLBACK_REPACKAGE_STOP:
243 rpmcliProgressTotal = total;
244 rpmcliProgressCurrent = total;
245 if (flags & INSTALL_HASH)
246 printHash(1, 1); /* Fixes "preparing..." progress bar */
247 rpmcliProgressTotal = rpmcliPackagesTotal;
248 rpmcliProgressCurrent = 0;
249 if (!(flags & INSTALL_LABEL))
250 break;
251 if (flags & INSTALL_HASH)
252 fprintf(stdout, "%-28s\n", _("Upgrading..."));
253 else
254 fprintf(stdout, "%s\n", _("Upgrading packages..."));
255 (void) fflush(stdout);
256 break;
257
258 case RPMCALLBACK_UNINST_PROGRESS:
259 break;
260 case RPMCALLBACK_UNINST_START:
261 break;
262 case RPMCALLBACK_UNINST_STOP:
263 break;
264 case RPMCALLBACK_UNPACK_ERROR:
265 break;
266 case RPMCALLBACK_CPIO_ERROR:
267 break;
268 case RPMCALLBACK_SCRIPT_ERROR:
269 break;
270 case RPMCALLBACK_UNKNOWN:
271 default:
272 break;
273 }
274
275 return rc;
276 }
277
278 int rpmcliInstallProblems(rpmts ts, const char * msg, int rc)
279 /*@globals fileSystem @*/
280 /*@modifies ts, fileSystem @*/
281 {
282 rpmps ps = rpmtsProblems(ts);
283
284 if (rc && rpmpsNumProblems(ps) > 0) {
285 if (msg)
286 rpmlog(RPMLOG_ERR, "%s:\n", msg);
287 rpmpsPrint(NULL, ps);
288 }
289 ps = rpmpsFree(ps);
290 return rc;
291 }
292
293 int rpmcliInstallSuggests(rpmts ts)
294 {
295 if (ts->suggests != NULL && ts->nsuggests > 0) {
296 const char * s;
297 int i;
298
299 rpmlog(RPMLOG_NOTICE, _(" Suggested resolutions:\n"));
300 for (i = 0; i < ts->nsuggests && (s = ts->suggests[i]) != NULL;
301 ts->suggests[i++] = s = _free(s))
302 {
303 rpmlog(RPMLOG_NOTICE, "\t%s\n", s);
304 }
305 ts->suggests = _free(ts->suggests);
306 }
307 return 0;
308 }
309
310 int rpmcliInstallCheck(rpmts ts)
311 {
312 /*@-evalorder@*/
313 return rpmcliInstallProblems(ts, _("Failed dependencies"), rpmtsCheck(ts));
314 /*@=evalorder@*/
315 }
316
317 int rpmcliInstallOrder(rpmts ts)
318 {
319 /*@-evalorder@*/
320 return rpmcliInstallProblems(ts, _("Ordering problems"), rpmtsOrder(ts));
321 /*@=evalorder@*/
322 }
323
324 int rpmcliInstallRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet)
325 {
326 /*@-evalorder@*/
327 return rpmcliInstallProblems(ts, _("Install/Erase problems"),
328 rpmtsRun(ts, okProbs, ignoreSet));
329 /*@=evalorder@*/
330 }
331
332 static rpmRC rpmcliEraseElement(rpmts ts, const char * arg)
333 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
334 /*@modifies ts, rpmGlobalMacroContext, fileSystem, internalState @*/
335 {
336 rpmmi mi;
337 Header h;
338 rpmRC rc = RPMRC_OK;
339 int xx;
340
341 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0);
342 if (mi == NULL)
343 return RPMRC_NOTFOUND;
344
345 while ((h = rpmmiNext(mi)) != NULL) {
346 unsigned int recOffset = rpmmiInstance(mi);
347
348 if (recOffset == 0) { /* XXX can't happen. */
349 rc = RPMRC_FAIL;
350 break;
351 }
352 xx = rpmtsAddEraseElement(ts, h, recOffset);
353 }
354 mi = rpmmiFree(mi);
355
356 return 0;
357 }
358
359 static const char * rpmcliWalkFirst(ARGV_t av, miRE mire)
360 /*@globals fileSystem, internalState @*/
361 /*@modifies mire, fileSystem, internalState @*/
362 {
363 /* XXX use global ftsOpts? */
364 /* XXX changing FTS_LOGICAL to FTS_PHYSICAL prevents symlink follow. */
365 /* XXX FTS_NOCHDIR is automatically assumed for URI's */
366 int _ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
367 FTS * ftsp = NULL;
368 FTSENT * fts;
369 const char * fn = NULL;
370 int fts_level = 1;
371 int xx;
372
373 if (av != NULL && av[0] != NULL)
374 ftsp = Fts_open((char *const *)av, _ftsOpts, NULL);
375 if (ftsp != NULL)
376 while((fts = Fts_read(ftsp)) != NULL) {
377 switch (fts->fts_info) {
378 /* No-op conditions. */
379 case FTS_D: /* preorder directory */
380 case FTS_DP: /* postorder directory */
381 /* XXX Don't recurse downwards, all elements should be files. */
382 if (fts_level > 0 && fts->fts_level >= fts_level)
383 xx = Fts_set(ftsp, fts, FTS_SKIP);
384 /*@fallthrough@*/
385 case FTS_DOT: /* dot or dot-dot */
386 continue;
387 /*@notreached@*/ /*@switchbreak@*/ break;
388 case FTS_F: /* regular file */
389 if (mireRegexec(mire, fts->fts_accpath, 0) < 0)
390 continue;
391 /*@switchbreak@*/ break;
392 /* Error conditions. */
393 case FTS_NS: /* stat(2) failed */
394 case FTS_DNR: /* unreadable directory */
395 case FTS_ERR: /* error; errno is set */
396 case FTS_DC: /* directory that causes cycles */
397 case FTS_DEFAULT: /* none of the above */
398 case FTS_INIT: /* initialized only */
399 case FTS_NSOK: /* no stat(2) requested */
400 case FTS_SL: /* symbolic link */
401 case FTS_SLNONE: /* symbolic link without target */
402 case FTS_W: /* whiteout object */
403 default:
404 goto exit;
405 /*@notreached@*/ /*@switchbreak@*/ break;
406 }
407
408 /* Stop on first file that matches. */
409 fn = xstrdup(fts->fts_accpath);
410 break;
411 }
412
413 exit:
414 xx = Fts_close(ftsp);
415 return fn;
416 }
417
418 static const char * rpmcliInstallElementPath(/*@unused@*/ rpmts ts,
419 const char * arg)
420 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
421 /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
422 {
423 /* A glob pattern list to match repository directories. */
424 const char * fn = rpmExpand(
425 "%{?_rpmgi_pattern_glob}"
426 "%{!?_rpmgi_pattern_glob:.}",
427 NULL
428 );
429 /* A regex pattern list to match candidate *.rpm files. */
430 const char * mirePattern = rpmExpand(
431 "%{?_rpmgi_pattern_regex:%{_rpmgi_pattern_regex ", arg, "}}"
432 "%{!?_rpmgi_pattern_regex:", arg, "-[^-]+-[^-]+\\.[^.]+\\.rpm$}",
433 NULL
434 );
435 miRE mire = mireNew(RPMMIRE_REGEX, 0);
436 ARGV_t dav = NULL;
437 int dac = 0;
438 ARGV_t av = NULL;
439 int xx = mireRegcomp(mire, mirePattern);
440 int i;
441
442 /* Get list of candidate repository patterns. */
443 xx = argvSplit(&dav, fn, ":");
444 fn = _free(fn);
445 if (xx || dav == NULL)
446 goto exit;
447
448 dac = argvCount(dav);
449 for (i = 0; i < dac; i++) {
450 ARGV_t nav = NULL;
451 int nac = 0;
452
453 /* Insure only directory paths are matched. */
454 fn = rpmGetPath(dav[i], "/", NULL);
455 xx = rpmGlob(fn, &nac, &nav);
456
457 /* Insure that final directory paths have trailing '/' */
458 if (nav != NULL)
459 for (i = 0; i < nac; i++) {
460 char * t = rpmExpand(nav[i], "/", NULL);
461 nav[i] = _free(nav[i]);
462 nav[i] = t;
463 }
464
465 /* Append matches to list of repository directories. */
466 if (nac > 0 && nav != NULL)
467 xx = argvAppend(&av, nav);
468 nav = argvFree(nav);
469 nac = 0;
470 fn = _free(fn);
471 }
472
473 /* Walk (possibly multi-root'd) directories, until 1st match is found. */
474 fn = rpmcliWalkFirst(av, mire);
475
476 exit:
477 av = argvFree(av);
478 dav = argvFree(dav);
479 mire = mireFree(mire);
480 mirePattern = _free(mirePattern);
481
482 return fn;
483 }
484
485 /*@-redef@*/ /* XXX Add rpmfi methods to make rpmRelocation opaque. */
486 struct rpmRelocation_s {
487 /*@only@*/ /*@null@*/
488 const char * oldPath;
489 /*@only@*/ /*@null@*/
490 const char * newPath;
491 };
492 /*@=redef@*/
493
495 int rpmcliInstall(rpmts ts, QVA_t ia, const char ** argv)
496 {
497 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
498 ARGV_t avfn = NULL;
499 int acfn = 0;
500 int numFailed = 0;
501 int numRPMS = 0;
502 rpmRelocation relocations = NULL;
503 rpmVSFlags vsflags, ovsflags;
504 rpmRC rpmrc;
505 int rc;
506 int xx;
507
508 if (argv == NULL) goto exit;
509
510 (void) rpmtsSetGoal(ts, TSM_INSTALL);
511 rpmcliPackagesTotal = 0;
512
513 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
514 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
515
516 (void) rpmtsSetFlags(ts, ia->transFlags);
517 (void) rpmtsSetDFlags(ts, ia->depFlags);
518
519 /* Display and set autorollback goal. */
520 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
521 if (ia->arbtid) {
522 time_t ttid = (time_t)ia->arbtid;
523 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
524 ctime(&ttid), ia->arbtid);
525 rpmtsSetARBGoal(ts, ia->arbtid);
526 }
527 }
528
529 if (ia->installInterfaceFlags & INSTALL_UPGRADE)
530 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
531 else
532 vsflags = rpmExpandNumeric("%{?_vsflags_install}");
533 if (ia->qva_flags & VERIFY_DIGEST)
534 vsflags |= _RPMVSF_NODIGESTS;
535 if (ia->qva_flags & VERIFY_SIGNATURE)
536 vsflags |= _RPMVSF_NOSIGNATURES;
537 if (ia->qva_flags & VERIFY_HDRCHK)
538 vsflags |= RPMVSF_NOHDRCHK;
539 ovsflags = rpmtsSetVSFlags(ts, (vsflags | RPMVSF_NEEDPAYLOAD));
540
541 { int notifyFlags;
542 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
543 xx = rpmtsSetNotifyCallback(ts,
544 rpmShowProgress, (void *) ((long)notifyFlags));
545 }
546
547 if ((relocations = ia->relocations) != NULL) {
548 while (relocations->oldPath)
549 relocations++;
550 if (relocations->newPath == NULL)
551 relocations = NULL;
552 }
553
554 { /* start-of-transaction-build */
555 int tag = (ia->qva_source == RPMQV_FTSWALK)
556 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST;
557 rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
558 rpmgiFlags _giFlags = RPMGI_NONE;
559 const char * fn = NULL;;
560
561 /*@-mods@*/
562 if (rpmioFtsOpts == 0)
563 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
564 /*@=mods@*/
565 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, _giFlags);
566 while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
567 Header h;
568
569 fn = _free(fn);
570 fn = xstrdup(rpmgiHdrPath(gi));
571
572 /* === Check for "+bing" lookaside paths within install transaction. */
573 if (fn[0] == '+') {
574 const char * nfn;
575 addMacro(NULL, "NEVRA", NULL, &fn[1], RMIL_GLOBAL);
576 nfn = rpmcliInstallElementPath(ts, &fn[1]);
577 delMacro(NULL, "NEVRA");
578 if (nfn == NULL) {
579 rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be found\n"), fn);
580 numFailed++; /* XXX multiple erasures? */
581 continue;
582 }
583 fn = _free(fn);
584 fn = nfn;
585 /* XXX hack into rpmgi innards for now ... */
586 h = rpmgiReadHeader(gi, fn);
587 if (h != NULL)
588 gi->h = headerLink(h);
589 (void)headerFree(h);
590 h = NULL;
591 }
592
593 /* === Check for "-bang" erasures within install transaction. */
594 if (fn[0] == '-') {
595 switch (rpmcliEraseElement(ts, &fn[1])) {
596 case RPMRC_OK:
597 numRPMS++; /* XXX multiple erasures? */
598 /*@switchbreak@*/ break;
599 case RPMRC_NOTFOUND:
600 default:
601 rpmlog(RPMLOG_ERR, _("package \"%s\" cannot be erased\n"), fn);
602 numFailed++; /* XXX multiple erasures? */
603 goto exit;
604 /*@notreached@*/ /*@switchbreak@*/ break;
605 }
606 continue;
607 }
608
609 h = rpmgiHeader(gi);
610 if (h == NULL) {
611 numFailed++;
612 continue;
613 }
614
615 /* === Check for relocatable package. */
616 if (relocations) {
617 he->tag = RPMTAG_PREFIXES;
618 xx = headerGet(h, he, 0);
619 if (xx && he->c == 1) {
620 relocations->oldPath = xstrdup(he->p.argv[0]);
621 he->p.ptr = _free(he->p.ptr);
622 } else {
623 he->p.ptr = _free(he->p.ptr);
624 he->tag = RPMTAG_NVRA;
625 xx = headerGet(h, he, 0);
626 rpmlog(RPMLOG_ERR,
627 _("package %s is not relocatable\n"), he->p.str);
628 he->p.ptr = _free(he->p.ptr);
629 numFailed++;
630 goto exit;
631 /*@notreached@*/
632 }
633 }
634
635 /* === On --freshen, verify package is installed and newer. */
636 if (ia->installInterfaceFlags & INSTALL_FRESHEN) {
637 rpmmi mi;
638 Header oldH;
639 int count;
640
641 he->tag = RPMTAG_NAME;
642 xx = headerGet(h, he, 0);
643 assert(xx != 0 && he->p.str != NULL);
644 mi = rpmtsInitIterator(ts, RPMTAG_NAME, he->p.str, 0);
645 he->p.ptr = _free(he->p.ptr);
646 count = rpmmiCount(mi);
647 while ((oldH = rpmmiNext(mi)) != NULL) {
648 if (rpmVersionCompare(oldH, h) < 0)
649 /*@innercontinue@*/ continue;
650 /* same or newer package already installed */
651 count = 0;
652 /*@innerbreak@*/ break;
653 }
654 mi = rpmmiFree(mi);
655 if (count == 0)
656 continue;
657 /* Package is newer than those currently installed. */
658 }
659
660 /* === Add binary package to transaction set. */
661 xx = argvAdd(&avfn, fn);
662 rc = rpmtsAddInstallElement(ts, h, (fnpyKey)avfn[acfn++],
663 (ia->installInterfaceFlags & INSTALL_UPGRADE) != 0,
664 ia->relocations);
665
666 if (relocations)
667 relocations->oldPath = _free(relocations->oldPath);
668
669 numRPMS++;
670 }
671
672 fn = _free(fn);
673 gi = rpmgiFree(gi);
674
675 } /* end-of-transaction-build */
676
677 /* XXX exit if the iteration failed. */
678 if (rpmrc == RPMRC_FAIL) numFailed = numRPMS;
679 if (numFailed) goto exit;
680
681 if (numRPMS) {
682 if (!(ia->installInterfaceFlags & INSTALL_NODEPS)
683 && (rc = rpmcliInstallCheck(ts)) != 0) {
684 numFailed = numRPMS;
685 (void) rpmcliInstallSuggests(ts);
686 }
687
688 if (!(ia->installInterfaceFlags & INSTALL_NOORDER)
689 && (rc = rpmcliInstallOrder(ts)) != 0)
690 numFailed = numRPMS;
691
692 /* Drop added/available package indices and dependency sets. */
693 rpmtsClean(ts);
694
695 /* XXX Avoid empty transaction msg, run iff there are elements. */
696 if (numFailed == 0 && rpmtsNElements(ts) > 0
697 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter)) != 0)
698 numFailed += (rc < 0 ? numRPMS : rc);
699 }
700
701 if (numFailed) goto exit;
702
703 exit:
704 avfn = argvFree(avfn);
705
706 #ifdef NOTYET /* XXX grrr, segfault in selabel_close */
707 if (!(ia->transFlags & RPMTRANS_FLAG_NOCONTEXTS))
708 matchpathcon_fini();
709 #endif
710
711 rpmtsEmpty(ts);
712
713 return numFailed;
714 }
715
716 int rpmErase(rpmts ts, QVA_t ia, const char ** argv)
717 {
718 int count;
719 const char ** arg;
720 int numFailed = 0;
721 int numRPMS = 0;
722 rpmVSFlags vsflags, ovsflags;
723 int rc;
724
725 if (argv == NULL) return 0;
726
727 vsflags = rpmExpandNumeric("%{?_vsflags_erase}");
728 if (ia->qva_flags & VERIFY_DIGEST)
729 vsflags |= _RPMVSF_NODIGESTS;
730 if (ia->qva_flags & VERIFY_SIGNATURE)
731 vsflags |= _RPMVSF_NOSIGNATURES;
732 if (ia->qva_flags & VERIFY_HDRCHK)
733 vsflags |= RPMVSF_NOHDRCHK;
734 ovsflags = rpmtsSetVSFlags(ts, vsflags);
735
736 if (rpmExpandNumeric("%{?_repackage_all_erasures}"))
737 ia->transFlags |= RPMTRANS_FLAG_REPACKAGE;
738
739 (void) rpmtsSetFlags(ts, ia->transFlags);
740 (void) rpmtsSetDFlags(ts, ia->depFlags);
741
742 /* Display and set autorollback goal. */
743 if (rpmExpandNumeric("%{?_rollback_transaction_on_failure}")) {
744 if (ia->arbtid) {
745 time_t ttid = (time_t)ia->arbtid;
746 rpmlog(RPMLOG_DEBUG, D_("Autorollback Goal: %-24.24s (0x%08x)\n"),
747 ctime(&ttid), ia->arbtid);
748 rpmtsSetARBGoal(ts, ia->arbtid);
749 }
750 }
751
752 #ifdef NOTYET /* XXX no callbacks on erase yet */
753 { int notifyFlags;
754 notifyFlags = ia->installInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
755 xx = rpmtsSetNotifyCallback(ts,
756 rpmShowProgress, (void *) ((long)notifyFlags));
757 }
758 #endif
759
760 (void) rpmtsSetGoal(ts, TSM_ERASE);
761
762 for (arg = argv; *arg; arg++) {
763 rpmmi mi;
764
765 /* XXX HACK to get rpmdbFindByLabel out of the API */
766 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
767 if (mi == NULL) {
768 rpmlog(RPMLOG_ERR, _("package %s is not installed\n"), *arg);
769 numFailed++;
770 } else {
771 Header h; /* XXX iterator owns the reference */
772 count = 0;
773 while ((h = rpmmiNext(mi)) != NULL) {
774 unsigned int recOffset = rpmmiInstance(mi);
775
776 if (!(count++ == 0 || (ia->installInterfaceFlags & INSTALL_ALLMATCHES))) {
777 rpmlog(RPMLOG_ERR, _("\"%s\" specifies multiple packages\n"),
778 *arg);
779 numFailed++;
780 /*@innerbreak@*/ break;
781 }
782 if (recOffset) {
783 (void) rpmtsAddEraseElement(ts, h, recOffset);
784 numRPMS++;
785 }
786 }
787 }
788 mi = rpmmiFree(mi);
789 }
790
791 if (numFailed == 0 && numRPMS > 0) {
792 if (!(ia->installInterfaceFlags & INSTALL_NODEPS)
793 && (rc = rpmcliInstallCheck(ts)) != 0)
794 numFailed = numRPMS;
795
796 if (numFailed == 0
797 && !(ia->installInterfaceFlags & INSTALL_NOORDER)
798 && (rc = rpmcliInstallOrder(ts)) != 0)
799 numFailed = numRPMS;
800
801 /* Drop added/available package indices and dependency sets. */
802 rpmtsClean(ts);
803
804 if (numFailed == 0
805 && (rc = rpmcliInstallRun(ts, NULL, ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES))) != 0)
806 numFailed += (rc < 0 ? numRPMS : rc);
807
808 }
809
810 rpmtsEmpty(ts);
811
812 return numFailed;
813 }
814
815 int rpmInstallSource(rpmts ts, const char * arg,
816 const char ** specFilePtr, const char ** cookie)
817 {
818 FD_t fd;
819 int rc;
820
821 fd = Fopen(arg, "r%{?_rpmgio}");
822 if (fd == NULL || Ferror(fd)) {
823 rpmlog(RPMLOG_ERR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
824 if (fd != NULL) (void) Fclose(fd);
825 return 1;
826 }
827
828 if (rpmIsVerbose())
829 fprintf(stdout, _("Installing %s\n"), arg);
830
831 {
832 rpmVSFlags ovsflags =
833 rpmtsSetVSFlags(ts, (rpmtsVSFlags(ts) | RPMVSF_NEEDPAYLOAD));
834 rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFilePtr, cookie);
835 rc = (rpmrc == RPMRC_OK ? 0 : 1);
836 ovsflags = rpmtsSetVSFlags(ts, ovsflags);
837 }
838 if (rc != 0) {
839 rpmlog(RPMLOG_ERR, _("%s cannot be installed\n"), arg);
840 /*@-unqualifiedtrans@*/
841 if (specFilePtr && *specFilePtr)
842 *specFilePtr = _free(*specFilePtr);
843 if (cookie && *cookie)
844 *cookie = _free(*cookie);
845 /*@=unqualifiedtrans@*/
846 }
847
848 (void) Fclose(fd);
849
850 return rc;
851 }