2 * \file lib/rpminstall.c
9 #include "depends.h" /* XXX ts->rpmdb */
11 #include "misc.h" /* XXX for rpmGlob() */
14 /*@access rpmTransactionSet @*/ /* XXX compared with NULL, ts->rpmdb */
15 /*@access rpmProblemSet @*/ /* XXX compared with NULL */
16 /*@access Header @*/ /* XXX compared with NULL */
17 /*@access rpmdb @*/ /* XXX compared with NULL */
18 /*@access FD_t @*/ /* XXX compared with NULL */
23 static int hashesPrinted = 0;
26 int packagesTotal = 0;
28 static int progressTotal = 0;
30 static int progressCurrent = 0;
34 static void printHash(const unsigned long amount, const unsigned long total)
35 /*@globals hashesPrinted, progressCurrent, fileSystem @*/
36 /*@modifies hashesPrinted, progressCurrent, fileSystem @*/
41 if (isatty (STDOUT_FILENO))
44 if (hashesPrinted != hashesTotal) {
45 hashesNeeded = hashesTotal * (total ? (((float) amount) / total) : 1);
46 while (hashesNeeded > hashesPrinted) {
47 if (isatty (STDOUT_FILENO)) {
49 for (i = 0; i < hashesPrinted; i++) (void) putchar ('#');
50 for (; i < hashesTotal; i++) (void) putchar (' ');
51 fprintf(stdout, "(%3d%%)",
52 (int)(100 * (total ? (((float) amount) / total) : 1)));
53 for (i = 0; i < (hashesTotal + 6); i++) (void) putchar ('\b');
59 (void) fflush(stdout);
60 hashesPrinted = hashesNeeded;
62 if (hashesPrinted == hashesTotal) {
65 if (isatty(STDOUT_FILENO)) {
66 for (i = 1; i < hashesPrinted; i++) (void) putchar ('#');
67 fprintf(stdout, " [%3d%%]", (int)(100 * (progressTotal ?
68 (((float) progressCurrent) / progressTotal) : 1)));
70 fprintf(stdout, "\n");
72 (void) fflush(stdout);
76 void * rpmShowProgress(/*@null@*/ const void * arg,
77 const rpmCallbackType what,
78 const unsigned long amount,
79 const unsigned long total,
80 /*@null@*/ fnpyKey key,
81 /*@null@*/ void * data)
82 /*@globals hashesPrinted, progressCurrent, progressTotal,
84 /*@modifies hashesPrinted, progressCurrent, progressTotal,
88 Header h = (Header) arg;
91 int flags = (int) ((long)data);
93 /*@-assignexpose -abstract @*/
94 const char * filename = (const char *)key;
95 /*@=assignexpose =abstract @*/
96 static FD_t fd = NULL;
99 case RPMCALLBACK_INST_OPEN_FILE:
100 if (filename == NULL || filename[0] == '\0')
102 fd = Fopen(filename, "r.ufdio");
103 /*@-type@*/ /* FIX: still necessary? */
105 fd = fdLink(fd, "persist (showProgress)");
108 /*@notreached@*/ break;
110 case RPMCALLBACK_INST_CLOSE_FILE:
111 /*@-type@*/ /* FIX: still necessary? */
112 fd = fdFree(fd, "persist (showProgress)");
120 case RPMCALLBACK_INST_START:
122 if (h == NULL || !(flags & INSTALL_LABEL))
124 if (flags & INSTALL_HASH) {
125 s = headerSprintf(h, "%{NAME}",
126 rpmTagTable, rpmHeaderFormats, NULL);
127 if (isatty (STDOUT_FILENO))
128 fprintf(stdout, "%4d:%-23.23s", progressCurrent + 1, s);
130 fprintf(stdout, "%-28.28s", s);
131 (void) fflush(stdout);
134 s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}",
135 rpmTagTable, rpmHeaderFormats, NULL);
136 fprintf(stdout, "%s\n", s);
137 (void) fflush(stdout);
142 case RPMCALLBACK_TRANS_PROGRESS:
143 case RPMCALLBACK_INST_PROGRESS:
144 if (flags & INSTALL_PERCENT)
145 fprintf(stdout, "%%%% %f\n", (double) (total
146 ? ((((float) amount) / total) * 100)
148 else if (flags & INSTALL_HASH)
149 printHash(amount, total);
150 (void) fflush(stdout);
153 case RPMCALLBACK_TRANS_START:
157 if (!(flags & INSTALL_LABEL))
159 if (flags & INSTALL_HASH)
160 fprintf(stdout, "%-28s", _("Preparing..."));
162 fprintf(stdout, "%s\n", _("Preparing packages for installation..."));
163 (void) fflush(stdout);
166 case RPMCALLBACK_TRANS_STOP:
167 if (flags & INSTALL_HASH)
168 printHash(1, 1); /* Fixes "preparing..." progress bar */
169 progressTotal = packagesTotal;
173 case RPMCALLBACK_UNINST_PROGRESS:
174 case RPMCALLBACK_UNINST_START:
175 case RPMCALLBACK_UNINST_STOP:
183 typedef /*@only@*/ /*@null@*/ const char * str_t;
190 /*@only@*/ str_t * pkgURL;
191 /*@dependent@*/ /*@null@*/ str_t * fnp;
192 /*@only@*/ char * pkgState;
197 /*@only@*/ /*@null@*/ str_t * sourceURL;
200 /*@only@*/ /*@null@*/ str_t * argv;
201 /*@temp@*/ rpmRelocation * relocations;
205 /** @todo Generalize --freshen policies. */
206 int rpmInstall(rpmTransactionSet ts, const char ** fileArgv,
207 rpmtransFlags transFlags,
208 rpmInstallInterfaceFlags interfaceFlags,
209 rpmprobFilterFlags probFilter,
210 rpmRelocation * relocations)
212 struct rpmEIU * eiu = memset(alloca(sizeof(*eiu)), 0, sizeof(*eiu));
213 int notifyFlags = interfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
214 /*@only@*/ /*@null@*/ const char * fileURL = NULL;
216 const char ** av = NULL;
222 if (fileArgv == NULL) goto exit;
225 ts->transFlags = transFlags;
226 ts->dbmode = (transFlags & RPMTRANS_FLAG_TEST)
227 ? O_RDONLY : (O_RDWR|O_CREAT);
228 ts->notify = rpmShowProgress;
229 ts->notifyData = (void *) ((long)notifyFlags);
231 if ((eiu->relocations = relocations) != NULL) {
232 while (eiu->relocations->oldPath)
234 if (eiu->relocations->newPath == NULL)
235 eiu->relocations = NULL;
238 /* Build fully globbed list of arguments in argv[argc]. */
241 for (eiu->fnp = fileArgv; *eiu->fnp != NULL; eiu->fnp++) {
243 av = _free(av); ac = 0;
244 rc = rpmGlob(*eiu->fnp, &ac, &av);
245 if (rc || ac == 0) continue;
247 eiu->argv = xrealloc(eiu->argv, (eiu->argc+ac+1) * sizeof(*eiu->argv));
248 memcpy(eiu->argv+eiu->argc, av, ac * sizeof(*av));
250 eiu->argv[eiu->argc] = NULL;
253 av = _free(av); ac = 0;
256 /* Allocate sufficient storage for next set of args. */
257 if (eiu->pkgx >= eiu->numPkgs) {
258 eiu->numPkgs = eiu->pkgx + eiu->argc;
259 eiu->pkgURL = xrealloc(eiu->pkgURL,
260 (eiu->numPkgs + 1) * sizeof(*eiu->pkgURL));
261 memset(eiu->pkgURL + eiu->pkgx, 0,
262 ((eiu->argc + 1) * sizeof(*eiu->pkgURL)));
263 eiu->pkgState = xrealloc(eiu->pkgState,
264 (eiu->numPkgs + 1) * sizeof(*eiu->pkgState));
265 memset(eiu->pkgState + eiu->pkgx, 0,
266 ((eiu->argc + 1) * sizeof(*eiu->pkgState)));
269 /* Retrieve next set of args, cache on local storage. */
270 for (i = 0; i < eiu->argc; i++) {
271 fileURL = _free(fileURL);
272 fileURL = eiu->argv[i];
275 switch (urlIsURL(fileURL)) {
281 fprintf(stdout, _("Retrieving %s\n"), fileURL);
284 const char * rootDir;
285 rootDir = (ts->rootDir && *ts->rootDir) ? ts->rootDir : "";
286 strcpy(tfnbuf, "rpm-xfer.XXXXXX");
287 (void) mktemp(tfnbuf);
288 tfn = rpmGenPath(rootDir, "%{_tmppath}/", tfnbuf);
291 /* XXX undefined %{name}/%{version}/%{release} here */
292 /* XXX %{_tmpdir} does not exist */
293 rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
294 rc = urlGetFile(fileURL, tfn);
296 rpmMessage(RPMMESS_ERROR,
297 _("skipping %s - transfer failed - %s\n"),
298 fileURL, ftpStrerror(rc));
300 eiu->pkgURL[eiu->pkgx] = NULL;
302 /*@switchbreak@*/ break;
304 eiu->pkgState[eiu->pkgx] = 1;
305 eiu->pkgURL[eiu->pkgx] = tfn;
307 } /*@switchbreak@*/ break;
310 eiu->pkgURL[eiu->pkgx] = fileURL;
313 /*@switchbreak@*/ break;
316 fileURL = _free(fileURL);
318 if (eiu->numFailed) goto exit;
320 /* Continue processing file arguments, building transaction set. */
321 for (eiu->fnp = eiu->pkgURL+eiu->prevx;
323 eiu->fnp++, eiu->prevx++)
325 const char * fileName;
327 rpmMessage(RPMMESS_DEBUG, "============== %s\n", *eiu->fnp);
328 (void) urlPath(*eiu->fnp, &fileName);
330 /* Try to read the header from a package file. */
331 eiu->fd = Fopen(*eiu->fnp, "r.ufdio");
332 if (eiu->fd == NULL || Ferror(eiu->fd)) {
333 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
336 xx = Fclose(eiu->fd);
339 eiu->numFailed++; *eiu->fnp = NULL;
343 ts->verify_legacy = 1;
344 /*@-mustmod -nullstate @*/ /* LCL: segfault */
345 eiu->rpmrc = rpmReadPackageFile(ts, eiu->fd, *eiu->fnp, &eiu->h);
346 /*@=mustmod =nullstate @*/
347 ts->verify_legacy = 0;
348 eiu->isSource = headerIsEntry(eiu->h, RPMTAG_SOURCEPACKAGE);
350 xx = Fclose(eiu->fd);
353 if (eiu->rpmrc == RPMRC_FAIL || eiu->rpmrc == RPMRC_SHORTREAD) {
354 eiu->numFailed++; *eiu->fnp = NULL;
359 (eiu->rpmrc == RPMRC_OK || eiu->rpmrc == RPMRC_BADSIZE))
361 rpmMessage(RPMMESS_DEBUG, "\tadded source package [%d]\n",
363 eiu->sourceURL = xrealloc(eiu->sourceURL,
364 (eiu->numSRPMS + 2) * sizeof(*eiu->sourceURL));
365 eiu->sourceURL[eiu->numSRPMS] = *eiu->fnp;
368 eiu->sourceURL[eiu->numSRPMS] = NULL;
372 if (eiu->rpmrc == RPMRC_OK || eiu->rpmrc == RPMRC_BADSIZE) {
374 /* Open database RDWR for binary packages. */
375 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
376 if (rpmtsOpenDB(ts, ts->dbmode)) {
380 /*@=nullstate@*/ /* FIX: ts->rootDir may be NULL? */
382 if (eiu->relocations) {
387 if (headerGetEntry(eiu->h, RPMTAG_PREFIXES, &pft,
388 (void **) &paths, &c) && (c == 1)) {
389 eiu->relocations->oldPath = xstrdup(paths[0]);
390 paths = headerFreeData(paths, pft);
393 xx = headerNVR(eiu->h, &name, NULL, NULL);
394 rpmMessage(RPMMESS_ERROR,
395 _("package %s is not relocateable\n"), name);
402 /* On --freshen, verify package is installed and newer */
403 if (interfaceFlags & INSTALL_FRESHEN) {
404 rpmdbMatchIterator mi;
409 xx = headerNVR(eiu->h, &name, NULL, NULL);
410 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
411 mi = rpmtsInitIterator(ts, RPMTAG_NAME, name, 0);
412 /*@=nullstate@*/ /* FIX: ts->rootDir may be NULL? */
413 count = rpmdbGetIteratorCount(mi);
414 while ((oldH = rpmdbNextIterator(mi)) != NULL) {
415 if (rpmVersionCompare(oldH, eiu->h) < 0)
416 /*@innercontinue@*/ continue;
417 /* same or newer package already installed */
419 /*@innerbreak@*/ break;
421 mi = rpmdbFreeIterator(mi);
423 eiu->h = headerFree(eiu->h, "Install freshen");
426 /* Package is newer than those currently installed. */
429 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
431 rc = rpmtransAddPackage(ts, eiu->h, (fnpyKey)fileName,
432 (interfaceFlags & INSTALL_UPGRADE) != 0,
437 /* XXX reference held by transaction set */
438 eiu->h = headerFree(eiu->h, "Install added");
439 if (eiu->relocations)
440 eiu->relocations->oldPath = _free(eiu->relocations->oldPath);
444 rpmMessage(RPMMESS_DEBUG, "\tadded binary package [%d]\n",
446 /*@switchbreak@*/ break;
448 rpmMessage(RPMMESS_ERROR,
449 _("error reading from file %s\n"), *eiu->fnp);
452 /*@notreached@*/ /*@switchbreak@*/ break;
454 rpmMessage(RPMMESS_ERROR,
455 _("file %s requires a newer version of RPM\n"),
459 /*@notreached@*/ /*@switchbreak@*/ break;
466 if (eiu->rpmrc != RPMRC_BADMAGIC) {
467 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *eiu->fnp);
468 eiu->numFailed++; *eiu->fnp = NULL;
472 /* Try to read a package manifest. */
473 eiu->fd = Fopen(*eiu->fnp, "r.fpio");
474 if (eiu->fd == NULL || Ferror(eiu->fd)) {
475 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), *eiu->fnp,
478 xx = Fclose(eiu->fd);
481 eiu->numFailed++; *eiu->fnp = NULL;
485 /* Read list of packages from manifest. */
486 rc = rpmReadPackageManifest(eiu->fd, &eiu->argc, &eiu->argv);
488 rpmError(RPMERR_MANIFEST, _("%s: read manifest failed: %s\n"),
489 *eiu->fnp, Fstrerror(eiu->fd));
490 xx = Fclose(eiu->fd);
493 /* If successful, restart the query loop. */
499 eiu->numFailed++; *eiu->fnp = NULL;
503 rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"),
504 eiu->numSRPMS, eiu->numRPMS);
506 if (eiu->numFailed) goto exit;
508 if (eiu->numRPMS && !(interfaceFlags & INSTALL_NODEPS)) {
509 rpmProblem conflicts;
512 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
513 if (rpmdepCheck(ts, &conflicts, &numConflicts)) {
514 eiu->numFailed = eiu->numPkgs;
520 if (!stopInstall && conflicts) {
521 rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
522 printDepProblems(stderr, conflicts, numConflicts);
523 conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
524 eiu->numFailed = eiu->numPkgs;
530 if (eiu->numRPMS && !(interfaceFlags & INSTALL_NOORDER)) {
531 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
532 if (rpmdepOrder(ts)) {
533 eiu->numFailed = eiu->numPkgs;
539 if (eiu->numRPMS && !stopInstall) {
540 rpmProblemSet probs = NULL;
542 packagesTotal = eiu->numRPMS + eiu->numSRPMS;
544 rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n"));
546 /*@-nullstate@*/ /* FIX: ts->rootDir may be NULL? */
547 rc = rpmRunTransactions(ts, ts->notify, ts->notifyData,
548 NULL, &probs, transFlags, probFilter);
552 eiu->numFailed += eiu->numRPMS;
554 eiu->numFailed += rc;
555 rpmProblemSetPrint(stderr, probs);
557 probs = rpmProblemSetFree(probs);
560 if (eiu->numSRPMS && !stopInstall) {
561 if (eiu->sourceURL != NULL)
562 for (i = 0; i < eiu->numSRPMS; i++) {
563 if (eiu->sourceURL[i] == NULL) continue;
564 eiu->fd = Fopen(eiu->sourceURL[i], "r.ufdio");
565 if (eiu->fd == NULL || Ferror(eiu->fd)) {
566 rpmMessage(RPMMESS_ERROR, _("cannot open file %s: %s\n"),
567 eiu->sourceURL[i], Fstrerror(eiu->fd));
569 xx = Fclose(eiu->fd);
575 if (!(transFlags & RPMTRANS_FLAG_TEST)) {
576 #if !defined(__LCLINT__) /* LCL: segfault */
577 eiu->rpmrc = rpmInstallSourcePackage(ts, eiu->fd, NULL,
578 ts->notify, ts->notifyData, NULL);
580 if (eiu->rpmrc != RPMRC_OK) eiu->numFailed++;
583 xx = Fclose(eiu->fd);
589 if (eiu->pkgURL != NULL)
590 for (i = 0; i < eiu->numPkgs; i++) {
591 if (eiu->pkgURL[i] == NULL) continue;
592 if (eiu->pkgState[i] == 1)
593 (void) Unlink(eiu->pkgURL[i]);
594 eiu->pkgURL[i] = _free(eiu->pkgURL[i]);
596 eiu->pkgState = _free(eiu->pkgState);
597 eiu->pkgURL = _free(eiu->pkgURL);
598 eiu->argv = _free(eiu->argv);
600 return eiu->numFailed;
603 int rpmErase(rpmTransactionSet ts, const char ** argv,
604 rpmtransFlags transFlags,
605 rpmEraseInterfaceFlags interfaceFlags)
611 rpmProblem conflicts;
613 int stopUninstall = 0;
617 if (argv == NULL) return 0;
619 ts->transFlags = transFlags;
620 /* XXX W2DO? O_EXCL??? */
621 ts->dbmode = (transFlags & RPMTRANS_FLAG_TEST)
622 ? O_RDONLY : (O_RDWR|O_EXCL);
624 (void) rpmtsOpenDB(ts, ts->dbmode);
626 for (arg = argv; *arg; arg++) {
627 rpmdbMatchIterator mi;
629 /* XXX HACK to get rpmdbFindByLabel out of the API */
630 mi = rpmtsInitIterator(ts, RPMDBI_LABEL, *arg, 0);
631 count = rpmdbGetIteratorCount(mi);
633 rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg);
635 } else if (!(count == 1 || (interfaceFlags & UNINSTALL_ALLMATCHES))) {
636 rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"),
640 Header h; /* XXX iterator owns the reference */
641 while ((h = rpmdbNextIterator(mi)) != NULL) {
642 unsigned int recOffset = rpmdbGetIteratorOffset(mi);
644 (void) rpmtransRemovePackage(ts, h, recOffset);
649 mi = rpmdbFreeIterator(mi);
652 if (!(interfaceFlags & UNINSTALL_NODEPS)) {
653 if (rpmdepCheck(ts, &conflicts, &numConflicts)) {
654 numFailed = numPackages;
659 if (!stopUninstall && conflicts) {
660 rpmMessage(RPMMESS_ERROR, _("removing these packages would break "
662 printDepProblems(stderr, conflicts, numConflicts);
663 conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
664 numFailed += numPackages;
670 if (!stopUninstall) {
671 transFlags |= RPMTRANS_FLAG_REVERSE;
672 numFailed += rpmRunTransactions(ts, NULL, NULL, NULL, &probs,
679 int rpmInstallSource(rpmTransactionSet ts, const char * arg,
680 const char ** specFile, const char ** cookie)
685 fd = Fopen(arg, "r.ufdio");
686 if (fd == NULL || Ferror(fd)) {
687 rpmMessage(RPMMESS_ERROR, _("cannot open %s: %s\n"), arg, Fstrerror(fd));
688 if (fd) (void) Fclose(fd);
693 fprintf(stdout, _("Installing %s\n"), arg);
696 rpmRC rpmrc = rpmInstallSourcePackage(ts, fd, specFile, NULL, NULL,
698 rc = (rpmrc == RPMRC_OK ? 0 : 1);
701 rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg);
702 /*@-unqualifiedtrans@*/
703 if (specFile && *specFile)
704 *specFile = _free(*specFile);
705 if (cookie && *cookie)
706 *cookie = _free(*cookie);
707 /*@=unqualifiedtrans@*/
716 static int reverse = -1;
720 static int IDTintcmp(const void * a, const void * b)
724 return ( reverse * (((IDT)a)->val.u32 - ((IDT)b)->val.u32) );
728 IDTX IDTXfree(IDTX idtx)
733 for (i = 0; i < idtx->nidt; i++) {
734 IDT idt = idtx->idt + i;
735 idt->h = headerFree(idt->h, "IDTXfree");
736 idt->key = _free(idt->key);
738 idtx->idt = _free(idtx->idt);
746 IDTX idtx = xcalloc(1, sizeof(*idtx));
748 idtx->size = sizeof(*((IDT)0));
752 IDTX IDTXgrow(IDTX idtx, int need)
754 if (need < 0) return NULL;
757 if (need == 0) return idtx;
759 if ((idtx->nidt + need) > idtx->alloced) {
761 idtx->alloced += idtx->delta;
764 idtx->idt = xrealloc(idtx->idt, (idtx->alloced * idtx->size) );
769 IDTX IDTXsort(IDTX idtx)
771 if (idtx != NULL && idtx->idt != NULL && idtx->nidt > 0)
772 qsort(idtx->idt, idtx->nidt, idtx->size, IDTintcmp);
776 IDTX IDTXload(rpmTransactionSet ts, rpmTag tag)
779 rpmdbMatchIterator mi;
780 HGE_t hge = (HGE_t) headerGetEntry;
784 mi = rpmtsInitIterator(ts, tag, NULL, 0);
785 while ((h = rpmdbNextIterator(mi)) != NULL) {
786 rpmTagType type = RPM_NULL_TYPE;
791 if (!hge(h, tag, &type, (void **)&tidp, &count) || tidp == NULL)
794 if (type == RPM_INT32_TYPE && (*tidp == 0 || *tidp == -1))
797 idtx = IDTXgrow(idtx, 1);
800 if (idtx->idt == NULL)
805 idt = idtx->idt + idtx->nidt;
807 idt->h = headerLink(h, "IDTXload idt->h");
809 idt->instance = rpmdbGetIteratorOffset(mi);
810 idt->val.u32 = *tidp;
814 mi = rpmdbFreeIterator(mi);
817 return IDTXsort(idtx);
820 IDTX IDTXglob(rpmTransactionSet ts, const char * globstr, rpmTag tag)
823 HGE_t hge = (HGE_t) headerGetEntry;
827 const char ** av = NULL;
834 rc = rpmGlob(globstr, &ac, &av);
837 for (i = 0; i < ac; i++) {
843 fd = Fopen(av[i], "r.ufdio");
844 if (fd == NULL || Ferror(fd)) {
845 rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), av[i],
847 if (fd) (void) Fclose(fd);
851 /*@-mustmod@*/ /* LCL: segfault */
852 xx = rpmReadPackageFile(ts, fd, av[i], &h);
854 rpmrc = (xx ? RPMRC_FAIL : RPMRC_OK); /* XXX HACK */
855 isSource = headerIsEntry(h, RPMTAG_SOURCEPACKAGE);
857 if (rpmrc != RPMRC_OK || isSource) {
864 if (hge(h, tag, &type, (void **) &tidp, &count) && tidp) {
866 idtx = IDTXgrow(idtx, 1);
867 if (idtx == NULL || idtx->idt == NULL) {
868 h = headerFree(h, "IDTXglob skip");
873 idt = idtx->idt + idtx->nidt;
874 idt->h = headerLink(h, "IDTXglob idt->h");
878 idt->val.u32 = *tidp;
884 h = headerFree(h, "IDTXglob next");
888 for (i = 0; i < ac; i++)
889 av[i] = _free(av[i]);
890 av = _free(av); ac = 0;
895 /** @todo Transaction handling, more, needs work. */
896 int rpmRollback(rpmTransactionSet ts,
897 struct rpmInstallArguments_s * ia,
902 rpmTransactionSet ts = NULL;
903 rpmDependencyConflict conflicts = NULL;
904 int numConflicts = 0;
905 rpmProblemSet probs = NULL;
906 int ifmask= (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL|INSTALL_ERASE);
907 unsigned thistid = 0xffffffff;
919 if (argv != NULL && *argv != NULL) {
924 itids = IDTXload(ts, RPMTAG_INSTALLTID);
933 { const char * globstr = rpmExpand("%{_repackage_dir}/*.rpm", NULL);
934 if (globstr == NULL || *globstr == '%') {
935 globstr = _free(globstr);
939 rtids = IDTXglob(ts, globstr, RPMTAG_REMOVETID);
947 globstr = _free(globstr);
951 /* Run transactions until rollback goal is achieved. */
956 ia->installInterfaceFlags &= ~ifmask;
958 /* Find larger of the remaining install/erase transaction id's. */
960 if (ip != NULL && ip->val.u32 > thistid)
961 thistid = ip->val.u32;
962 if (rp != NULL && rp->val.u32 > thistid)
963 thistid = rp->val.u32;
965 /* If we've achieved the rollback goal, then we're done. */
966 if (thistid == 0 || thistid < ia->rbtid)
969 /* Install the previously erased packages for this transaction. */
970 while (rp != NULL && rp->val.u32 == thistid) {
972 rpmMessage(RPMMESS_DEBUG, "\t+++ %s\n", rp->key);
974 rc = rpmtransAddPackage(ts, rp->h, (fnpyKey)rp->key,
980 if (!(ia->installInterfaceFlags & ifmask))
981 ia->installInterfaceFlags |= INSTALL_UPGRADE;
984 rp->h = headerFree(rp->h);
993 /* Erase the previously installed packages for this transaction. */
994 while (ip != NULL && ip->val.u32 == thistid) {
996 rpmMessage(RPMMESS_DEBUG,
997 "\t--- rpmdb instance #%u\n", ip->instance);
999 rc = rpmtransRemovePackage(ts, ip->instance);
1004 if (!(ia->installInterfaceFlags & ifmask))
1005 ia->installInterfaceFlags |= INSTALL_ERASE;
1017 /* Anything to do? */
1018 if (packagesTotal <= 0)
1021 tid = (time_t)thistid;
1022 rpmMessage(RPMMESS_DEBUG, _("rollback %d packages to %s"),
1023 packagesTotal, ctime(&tid));
1027 rc = rpmdepCheck(ts, &conflicts, &numConflicts);
1029 rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n"));
1030 printDepProblems(stderr, conflicts, numConflicts);
1031 conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
1035 rc = rpmdepOrder(ts);
1040 rc = rpmRunTransactions(ts, rpmShowProgress,
1041 (void *) ((long)ia->installInterfaceFlags),
1042 NULL, &probs, ia->transFlags,
1043 (ia->probFilter|RPMPROB_FILTER_OLDPACKAGE));
1045 rpmProblemSetPrint(stderr, probs);
1046 if (probs != NULL) rpmProblemSetFree(probs);
1056 rtids = IDTXfree(rtids);
1057 itids = IDTXfree(itids);