From 6fef7c55e95b1d7481132b23da3435958e66ed3a Mon Sep 17 00:00:00 2001 From: jbj Date: Wed, 14 Jul 1999 15:28:03 +0000 Subject: [PATCH] Create from top level install.c. CVS patchset: 3154 CVS date: 1999/07/14 15:28:03 --- lib/rpminstall.c | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 lib/rpminstall.c diff --git a/lib/rpminstall.c b/lib/rpminstall.c new file mode 100644 index 0000000..60aeeaa --- /dev/null +++ b/lib/rpminstall.c @@ -0,0 +1,466 @@ +#include "system.h" + +#include "build/rpmbuild.h" + +#include "install.h" +#include "rpmurl.h" + +static void printHash(const unsigned long amount, const unsigned long total); +static void * showProgress(const Header h, const rpmCallbackType what, + const unsigned long amount, + const unsigned long total, + const void * pkgKey, void * data); + +static int hashesPrinted = 0; + +static void printHash(const unsigned long amount, const unsigned long total) { + int hashesNeeded; + + if (hashesPrinted != 50) { + hashesNeeded = 50 * (total ? (((float) amount) / total) : 1); + while (hashesNeeded > hashesPrinted) { + printf("#"); + fflush(stdout); + hashesPrinted++; + } + fflush(stdout); + hashesPrinted = hashesNeeded; + + if (hashesPrinted == 50) + fprintf(stdout, "\n"); + } +} + +static void * showProgress(const Header h, const rpmCallbackType what, + const unsigned long amount, + const unsigned long total, + const void * pkgKey, void * data) { + char * s; + int flags = (int) data; + void * rc = NULL; + const char * filename = pkgKey; + static FD_t fd; + + switch (what) { + case RPMCALLBACK_INST_OPEN_FILE: + fd = fdOpen(filename, O_RDONLY, 0); + return fd; + + case RPMCALLBACK_INST_CLOSE_FILE: + fdClose(fd); + break; + + case RPMCALLBACK_INST_START: + hashesPrinted = 0; + if (flags & INSTALL_LABEL) { + if (flags & INSTALL_HASH) { + s = headerSprintf(h, "%{NAME}", + rpmTagTable, rpmHeaderFormats, NULL); + printf("%-28s", s); + fflush(stdout); + } else { + s = headerSprintf(h, "%{NAME}-%{VERSION}-%{RELEASE}", + rpmTagTable, rpmHeaderFormats, NULL); + printf("%s\n", s); + } + free(s); + } + break; + + case RPMCALLBACK_INST_PROGRESS: + if (flags & INSTALL_PERCENT) { + fprintf(stdout, "%%%% %f\n", (total + ? ((float) ((((float) amount) / total) * 100)) + : 100.0)); + } else if (flags & INSTALL_HASH) { + printHash(amount, total); + } + break; + + case RPMCALLBACK_TRANS_PROGRESS: + case RPMCALLBACK_TRANS_START: + case RPMCALLBACK_TRANS_STOP: + case RPMCALLBACK_UNINST_PROGRESS: + case RPMCALLBACK_UNINST_START: + case RPMCALLBACK_UNINST_STOP: + /* ignore */ + break; + } + + return rc; +} + +int doInstall(const char * rootdir, const char ** argv, int transFlags, + int interfaceFlags, int probFilter, + rpmRelocation * relocations) { + rpmdb db = NULL; + FD_t fd; + int i; + int mode, rc, major; + const char ** packages, ** tmpPackages; + const char ** filename; + int numPackages; + int numTmpPackages = 0, numBinaryPackages = 0, numSourcePackages = 0; + int numFailed = 0; + Header h; + int isSource; + rpmTransactionSet rpmdep = NULL; + struct rpmDependencyConflict * conflicts; + int numConflicts; + int stopInstall = 0; + size_t nb; + int notifyFlags = interfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 ); + int dbIsOpen = 0; + const char ** sourcePackages; + rpmRelocation * defaultReloc; + + if (transFlags & RPMTRANS_FLAG_TEST) + mode = O_RDONLY; + else + mode = O_RDWR | O_CREAT; + + for (defaultReloc = relocations; defaultReloc && defaultReloc->oldPath; + defaultReloc++); + if (defaultReloc && !defaultReloc->newPath) defaultReloc = NULL; + + rpmMessage(RPMMESS_DEBUG, _("counting packages to install\n")); + for (filename = argv, numPackages = 0; *filename; filename++, numPackages++) + ; + + rpmMessage(RPMMESS_DEBUG, _("found %d packages\n"), numPackages); + + nb = (numPackages + 1) * sizeof(char *); + packages = alloca(nb); + memset(packages, 0, nb); + tmpPackages = alloca(nb); + memset(tmpPackages, 0, nb); + nb = (numPackages + 1) * sizeof(Header); + + rpmMessage(RPMMESS_DEBUG, _("looking for packages to download\n")); + for (filename = argv, i = 0; *filename; filename++) { + + switch (urlIsURL(*filename)) { + case URL_IS_FTP: + case URL_IS_HTTP: + case URL_IS_PATH: + { int myrc; + const char *tfn; + + if (rpmIsVerbose()) + fprintf(stdout, _("Retrieving %s\n"), *filename); + + { char tfnbuf[64]; + strcpy(tfnbuf, "rpm-xfer.XXXXXX"); + /* XXX watchout for rootdir = NULL */ + tfn = rpmGetPath( (rootdir ? rootdir : ""), + "%{_tmppath}/", mktemp(tfnbuf), NULL); + } + + rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn); + myrc = urlGetFile(*filename, tfn); + if (myrc < 0) { + rpmMessage(RPMMESS_ERROR, + _("skipping %s - transfer failed - %s\n"), + *filename, ftpStrerror(myrc)); + numFailed++; + packages[i] = NULL; + xfree(tfn); + } else { + tmpPackages[numTmpPackages++] = packages[i++] = tfn; + } + } break; + default: + packages[i++] = *filename; + break; + } + } + + sourcePackages = alloca(sizeof(*sourcePackages) * i); + + rpmMessage(RPMMESS_DEBUG, _("retrieved %d packages\n"), numTmpPackages); + + /* Build up the transaction set. As a special case, v1 source packages + are installed right here, only because they don't have headers and + would create all sorts of confusion later. */ + + for (filename = packages; *filename; filename++) { + fd = fdOpen(*filename, O_RDONLY, 0); + if (fdFileno(fd) < 0) { + rpmMessage(RPMMESS_ERROR, _("cannot open file %s\n"), *filename); + numFailed++; + packages[i] = NULL; + continue; + } + + rc = rpmReadPackageHeader(fd, &h, &isSource, &major, NULL); + + switch (rc) { + case 1: + fdClose(fd); + rpmMessage(RPMMESS_ERROR, + _("%s does not appear to be a RPM package\n"), + *filename); + break; + default: + rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), *filename); + numFailed++; + packages[i] = NULL; + break; + case 0: + if (isSource) { + sourcePackages[numSourcePackages++] = *filename; + fdClose(fd); + } else { + if (!dbIsOpen) { + if (rpmdbOpen(rootdir, &db, mode, 0644)) { + const char *dn; + dn = rpmGetPath( (rootdir ? rootdir : ""), + "%{_dbpath}", NULL); + rpmMessage(RPMMESS_ERROR, + _("cannot open %s/packages.rpm\n"), dn); + xfree(dn); + exit(EXIT_FAILURE); + } + rpmdep = rpmtransCreateSet(db, rootdir); + dbIsOpen = 1; + } + + if (defaultReloc) { + char ** paths; + char * name; + int c; + + if (headerGetEntry(h, RPMTAG_PREFIXES, NULL, + (void **) &paths, &c) && (c == 1)) { + defaultReloc->oldPath = strdup(paths[0]); + free(paths); + } else { + headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, + NULL); + rpmMessage(RPMMESS_ERROR, + _("package %s is not relocateable\n"), name); + + return numPackages; + } + } + + rc = rpmtransAddPackage(rpmdep, h, NULL, *filename, + (interfaceFlags & INSTALL_UPGRADE) != 0, + relocations); + if (rc) { + if (rc == 1) + rpmMessage(RPMMESS_ERROR, + _("error reading from file %s\n"), *filename); + else if (rc == 2) + rpmMessage(RPMMESS_ERROR, + _("file %s requires a newer version of RPM\n"), + *filename); + return numPackages; + } + + if (defaultReloc) { + free(defaultReloc->oldPath); + defaultReloc->oldPath = NULL; + } + + fdClose(fd); + numBinaryPackages++; + } + break; + } + } + + rpmMessage(RPMMESS_DEBUG, _("found %d source and %d binary packages\n"), + numSourcePackages, numBinaryPackages); + + if (numBinaryPackages && !(interfaceFlags & INSTALL_NODEPS)) { + if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) { + numFailed = numPackages; + stopInstall = 1; + } + + if (!stopInstall && conflicts) { + rpmMessage(RPMMESS_ERROR, _("failed dependencies:\n")); + printDepProblems(stderr, conflicts, numConflicts); + rpmdepFreeConflicts(conflicts, numConflicts); + numFailed = numPackages; + stopInstall = 1; + } + } + + if (numBinaryPackages && !(interfaceFlags & INSTALL_NOORDER)) { + if (rpmdepOrder(rpmdep)) { + numFailed = numPackages; + stopInstall = 1; + } + } + + if (numBinaryPackages && !stopInstall) { + rpmProblemSet probs = NULL; +; + rpmMessage(RPMMESS_DEBUG, _("installing binary packages\n")); + rc = rpmRunTransactions(rpmdep, showProgress, (void *) notifyFlags, + NULL, &probs, transFlags, probFilter); + + if (rc < 0) { + numFailed += numBinaryPackages; + } else if (rc) { + numFailed += rc; + rpmProblemSetPrint(stderr, probs); + } + + if (probs) rpmProblemSetFree(probs); + } + + if (numBinaryPackages) rpmtransFree(rpmdep); + + if (numSourcePackages && !stopInstall) { + for (i = 0; i < numSourcePackages; i++) { + fd = fdOpen(sourcePackages[i], O_RDONLY, 0); + if (fdFileno(fd) < 0) { + rpmMessage(RPMMESS_ERROR, _("cannot open file %s\n"), + sourcePackages[i]); + continue; + } + + if (!(transFlags & RPMTRANS_FLAG_TEST)) + numFailed += rpmInstallSourcePackage(rootdir, fd, NULL, + showProgress, (void *) notifyFlags, NULL); + + fdClose(fd); + } + } + + for (i = 0; i < numTmpPackages; i++) { + unlink(tmpPackages[i]); + xfree(tmpPackages[i]); + } + + /* FIXME how do we close our various fd's? */ + + if (dbIsOpen) rpmdbClose(db); + + return numFailed; +} + +int doUninstall(const char * rootdir, const char ** argv, int transFlags, + int interfaceFlags) { + rpmdb db; + dbiIndexSet matches; + int i, j; + int mode; + int rc; + int count; + const char ** arg; + int numFailed = 0; + rpmTransactionSet rpmdep; + struct rpmDependencyConflict * conflicts; + int numConflicts; + int stopUninstall = 0; + int numPackages = 0; + rpmProblemSet probs; + + if (transFlags & RPMTRANS_FLAG_TEST) + mode = O_RDONLY; + else + mode = O_RDWR | O_EXCL; + + if (rpmdbOpen(rootdir, &db, mode, 0644)) { + const char *dn; + dn = rpmGetPath( (rootdir ? rootdir : ""), "%{_dbpath}", NULL); + rpmMessage(RPMMESS_ERROR, _("cannot open %s/packages.rpm\n"), dn); + xfree(dn); + exit(EXIT_FAILURE); + } + + j = 0; + rpmdep = rpmtransCreateSet(db, rootdir); + for (arg = argv; *arg; arg++) { + rc = rpmdbFindByLabel(db, *arg, &matches); + switch (rc) { + case 1: + rpmMessage(RPMMESS_ERROR, _("package %s is not installed\n"), *arg); + numFailed++; + break; + case 2: + rpmMessage(RPMMESS_ERROR, _("searching for package %s\n"), *arg); + numFailed++; + break; + default: + count = 0; + for (i = 0; i < dbiIndexSetCount(matches); i++) + if (dbiIndexRecordOffset(matches, i)) count++; + + if (count > 1 && !(interfaceFlags & UNINSTALL_ALLMATCHES)) { + rpmMessage(RPMMESS_ERROR, _("\"%s\" specifies multiple packages\n"), + *arg); + numFailed++; + } + else { + for (i = 0; i < dbiIndexSetCount(matches); i++) { + unsigned int recOffset = dbiIndexRecordOffset(matches, i); + if (recOffset) { + rpmtransRemovePackage(rpmdep, recOffset); + numPackages++; + } + } + } + + dbiFreeIndexRecord(matches); + break; + } + } + + if (!(interfaceFlags & UNINSTALL_NODEPS)) { + if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) { + numFailed = numPackages; + stopUninstall = 1; + } + + if (!stopUninstall && conflicts) { + rpmMessage(RPMMESS_ERROR, _("removing these packages would break " + "dependencies:\n")); + printDepProblems(stderr, conflicts, numConflicts); + rpmdepFreeConflicts(conflicts, numConflicts); + numFailed += numPackages; + stopUninstall = 1; + } + } + + if (!stopUninstall) { + numFailed += rpmRunTransactions(rpmdep, NULL, NULL, NULL, &probs, + transFlags, 0); + } + + rpmtransFree(rpmdep); + rpmdbClose(db); + + return numFailed; +} + +int doSourceInstall(const char * rootdir, const char * arg, const char ** specFile, + char ** cookie) { + FD_t fd; + int rc; + + fd = fdOpen(arg, O_RDONLY, 0); + if (fdFileno(fd) < 0) { + rpmMessage(RPMMESS_ERROR, _("cannot open %s\n"), arg); + return 1; + } + + if (rpmIsVerbose()) + fprintf(stdout, _("Installing %s\n"), arg); + + rc = rpmInstallSourcePackage(rootdir, fd, specFile, NULL, NULL, + cookie); + if (rc == 1) { + rpmMessage(RPMMESS_ERROR, _("%s cannot be installed\n"), arg); + if (specFile) FREE(*specFile); + if (cookie) FREE(*cookie); + } + + fdClose(fd); + + return rc; +} -- 2.7.4