#include #include #include #include #include #include #include /* for mkdir(2) ?!? */ #include #include #include #include #include #include "config.h" #include "doit.h" #include "install.h" #include "intl.h" #include "kbd.h" #include "kickstart.h" #include "log.h" #include "syslog.h" #include "windows.h" extern int testing; FILE * logFile = NULL; static int installPackage(rpmdb db, char * rootPath, struct installMethod * method, struct packageInfo * pkg, int errfd, int flags); static void setupXfree(struct installMethod * method, rpmdb db, char * rootPath, struct pkgSet * psp, int errfd); static void rpmerror(void); static void swOpen(int numPackages, int sizePackages); static void swPackage(Header h); static void swPackageComplete(); static void swClose(void); static void swCallback(const unsigned long amount, const unsigned long total); static void formatTime(char * buf, time_t t); int doInstall(struct installMethod * method, char * rootPath, struct pkgSet * psp, char * netSharedPath, char * keymap, int upgrade) { int i, totalNumPackages, totalSizePackages; struct packageInfo ** orderedPackages; int flags = 0; rpmdb db; int errfd; char * logFileName = "/dev/tty5"; char * path; rpmDependencies rpmdeps, rpmorder; char * hostEntry = "127.0.0.1 localhost localhost.localdomain\n"; int fd; if (testing) return 0; path = alloca(strlen(rootPath) + 20); fd = open(".", O_RDONLY); chdir(rootPath); mkdir("dev", 0755); mkdir("etc", 0755); mkdir("tmp", 0755); mkdir("var", 0755); mkdir("var/tmp", 0755); mkdir("var/lib", 0755); mkdir("var/lib/rpm", 0755); fchdir(fd); close(fd); #ifdef __sparc__ logMessage("removing /mnt/usr/X11R6 symlink"); unlink("/mnt/usr/X11R6"); #endif handleSyslogSocket(rootPath); if (!upgrade) { sprintf(path, "%s/etc/hosts", rootPath); fd = open(path, O_CREAT | O_RDWR, 0644); if (fd < 0) { errorWindow("Failed to create etc/hosts: %s."); return INST_ERROR; } write(fd, hostEntry, strlen(hostEntry)); close(fd); } sprintf(path, "%s/tmp/%s.log", rootPath, upgrade ? "upgrade" : "install"); if (upgrade) flags |= RPMINSTALL_UPGRADE | RPMINSTALL_REPLACEFILES; logFile = fopen(path, "w"); if (logFile) { setlinebuf(logFile); logMessage("opened %s", path); } else { logMessage("failed to open %s :-(", path); newtWinMessage(_("Error"), _("Ok"), _("Failed to open %s. No upgrade log will be kept."), path); } errfd = open(logFileName, O_APPEND | O_CREAT, 0644); if (errfd < 0) { logMessage("failed to open /dev/tty5!"); logFileName = "/tmp/exec.log"; errfd = open(logFileName, O_APPEND | O_CREAT, 0644); if (errfd < 0) { logMessage("failed to open %s: %s!\n", logFileName, strerror(errno)); errfd = 2; } } rpmErrorSetCallback(rpmerror); /* FIXME: we ought to read /mnt/us/lib/rpmrc if we're in the midst of an upgrade, but it's not obvious how to get RPM to do that. */ rpmSetVar(RPMVAR_NETSHAREDPATH, netSharedPath); if (rpmdbOpen(rootPath, &db, O_RDWR | O_CREAT, 0644)) { errorWindow(_("Fatal error opening RPM database")); return INST_ERROR; } logMessage("opened rpm database"); rpmdeps = rpmdepDependencies(db); rpmorder = rpmdepDependencies(NULL); for (i = 0; i < psp->numPackages; i++) { if (!strcmp(psp->packages[i]->name, "basesystem")) { rpmdepAddPackage(rpmdeps, psp->packages[i]->h, psp->packages[i]); rpmdepAddPackage(rpmorder, psp->packages[i]->h, psp->packages[i]); } } totalNumPackages = 0, totalSizePackages = 0; for (i = 0; i < psp->numPackages; i++) { if (psp->packages[i]->selected) { if (strcmp(psp->packages[i]->name, "basesystem")) { rpmdepAddPackage(rpmdeps, psp->packages[i]->h, psp->packages[i]); rpmdepAddPackage(rpmorder, psp->packages[i]->h, psp->packages[i]); } totalSizePackages += psp->packages[i]->size; totalNumPackages++; } } if (rpmdepOrder(rpmorder, (void ***) &orderedPackages)) { rpmdbClose(db); newtWinMessage(_("Error"), _("Ok"), _("Error ordering package list: %s"), rpmErrorString()); close(errfd); return 1; } rpmdepDone(rpmdeps); rpmdepDone(rpmorder); if (testing) { newtWinMessage("Status", "Ok", "Packages would be installed now"); return 0; } swOpen(totalNumPackages, totalSizePackages); logMessage("installing %d packages", totalNumPackages); for (i = 0; i < totalNumPackages; i++) { installPackage(db, rootPath, method, orderedPackages[i], errfd, flags); } swClose(); free(orderedPackages); #ifndef __sparc__ if (!upgrade) { sprintf(path, "%s/etc/sysconfig", rootPath); mkdir(path, 0755); writeKbdConfig(path, keymap); } #endif if (!upgrade) { mouseConfig(rootPath); writeLangInfo(rootPath); setupXfree(method, db, rootPath, psp, errfd); } rpmdbClose(db); close(errfd); #ifdef __sparc__ logMessage("making /etc/X11/X symlink"); symlink("../../usr/X11R6/bin/Xsun", "/mnt/etc/X11/X"); #endif if (logFile) fclose(logFile); logMessage("rpm database closed"); return 0; } static int installPackage(rpmdb db, char * rootPath, struct installMethod * method, struct packageInfo * pkg, int errfd, int flags) { int fd, olderr; char * realName; int olderrno, rc; if (logFile) fprintf(logFile, "%s %s.\n", (flags & RPMINSTALL_UPGRADE) ? _("Upgrading") : _("Installing"), pkg->name); swPackage(pkg->h); if (method->getFile(method, pkg->data, &realName)) { logMessage("getFile method failed for %s", pkg->data); if (logFile) fprintf(logFile, "Failed to get file for package %s.\n", pkg->name); swPackageComplete(); return 1; } fd = open(realName, O_RDONLY); if (fd < 0) { olderrno = errno; logMessage("cannot open RPM file %s: %s", pkg->data, strerror(olderrno)); newtWinMessage(_("Error"), _("Ok"), _("Error installing package: cannot open RPM file " "for %s: %s"), pkg->data, strerror(errno)); if (logFile) fprintf(logFile, "\tcannot open RPM file %s: %s\n", (char *) pkg->data, strerror(olderrno)); swPackageComplete(); return 1; } /* this is a hack */ if (!strcmp(pkg->name, "lilo") || !strcmp(pkg->name, "kernel")) flags |= RPMINSTALL_NOSCRIPTS; olderr = dup(2); dup2(errfd, 2); rc = rpmInstallPackage(rootPath, db, fd, NULL, flags | RPMINSTALL_REPLACEPKG | RPMINSTALL_REPLACEFILES, swCallback, NULL); dup2(olderr, 2); close(olderr); if (rc) { olderrno = errno; logMessage("Error installing package: package install of " "%s failed: %s", pkg->name, rpmErrorString()); newtWinMessage(_("Error"), _("Ok"), _("RPM install of %s failed: %s"), pkg->name, rpmErrorString()); if (logFile) fprintf(logFile, "\tcannot open RPM file %s: %s\n", (char *) pkg->data, strerror(olderrno)); } close(fd); swPackageComplete(); if (method->rmFiles) unlink(realName); return 0; } static void setupXfree(struct installMethod * method, rpmdb db, char * rootPath, struct pkgSet * psp, int errfd) { int fd, i; char buf[200], * chptr; char server[50]; int rc; char * path; char * procPath; path = alloca(strlen(rootPath) + 200); procPath = alloca(strlen(rootPath) + 50); sprintf(path, "%s/usr/X11R6/bin/Xconfigurator", rootPath); /* This is a cheap trick to see if our X component was installed */ if (access(path, X_OK)) { logMessage("%s cannot be run", path); return; } /* need proc to do pci probing */ sprintf(procPath, "%s/proc", rootPath); if ((rc = doMount("/proc", procPath, "proc", 0, 0))) { return; } /* this handles kickstart and normal/expert modes */ if ((rc=xfree86Config(rootPath, "--pick"))) return; sprintf(path, "%s/tmp/SERVER", rootPath); if ((fd = open(path, O_RDONLY)) < 0) { logMessage("failed to open %s: %s", path, strerror(errno)); return; } buf[0] = '\0'; read(fd, buf, sizeof(buf)); close(fd); chptr = buf; while (chptr < (buf + sizeof(buf) - 1) && *chptr && *chptr != ' ') chptr++; if (chptr >= (buf + sizeof(buf) - 1) || *chptr != ' ') { logMessage("couldn't find ' ' in %s", path); return; } *chptr = '\0'; strcpy(server, "XFree86-"); strcat(server, buf); logMessage("I will install the %s package", server); for (i = 0; i < psp->numPackages; i++) { if (!strcmp(psp->packages[i]->name, server)) { logMessage("\tfound package: %s", psp->packages[i]->name); swOpen(1, psp->packages[i]->size); installPackage(db, rootPath, method, psp->packages[i], errfd, 0); swClose(); break; } } /* this handles kickstart and normal/expert modes */ if ((rc=xfree86Config(rootPath, "--continue"))) return; /* done with proc now */ umount(procPath); } static void rpmerror(void) { int code; code = rpmErrorCode(); if (code != RPMERR_UNLINK && code != RPMERR_RMDIR) { if (logFile) fprintf(logFile, "%s\n", rpmErrorString()); else logMessage(rpmErrorString()); } } static struct statusWindowInfo { newtComponent form, packageLabel, sizeLabel, summaryText; newtComponent pkgScale, globalScale; newtComponent pkgDoneLabel, pkgRemainsLabel; newtComponent sizeDoneLabel, sizeRemainsLabel; newtComponent timeDoneLabel, timeRemainsLabel, timeTotalLabel; int numPackages, packagesDone; unsigned int sizePackages, sizeDone; int thisPackageSize; time_t timeStarted; } si; static void swOpen(int numPackages, int sizePackages) { char buf[50]; newtCenteredWindow(60, 15, _("Install Status")); si.form = newtForm(NULL, NULL, 0); newtFormAddComponent(si.form, newtLabel(1, 1, "Package:")); newtFormAddComponent(si.form, newtLabel(1, 2, "Size :")); newtFormAddComponent(si.form, newtLabel(1, 3, "Summary:")); si.packageLabel = newtLabel(13, 1, ""); si.sizeLabel = newtLabel(13, 2, ""); si.summaryText = newtTextbox(13, 3, 45, 2, NEWT_TEXTBOX_WRAP); si.pkgScale = newtScale(3, 6, 54, 100); newtFormAddComponent(si.form, newtLabel(1, 8, " Packages Bytes Time")); /* 12345678901234567890123456789012345678901234567 1 2 3 4 */ newtFormAddComponent(si.form, newtLabel(1, 9, "Total :")); newtFormAddComponent(si.form, newtLabel(1, 10, "Completed :")); newtFormAddComponent(si.form, newtLabel(1, 11, "Remaining :")); si.numPackages = numPackages; si.sizePackages = sizePackages; si.packagesDone = 0; si.sizeDone = 0; si.timeStarted = time(NULL); sprintf(buf, "%8d", numPackages); newtFormAddComponent(si.form, newtLabel(14, 9, buf)); si.pkgDoneLabel = newtLabel(14, 10, ""); si.pkgRemainsLabel = newtLabel(14, 11, ""); sprintf(buf, "%4uM", sizePackages / (1024 * 1024)); newtFormAddComponent(si.form, newtLabel(29, 9, buf)); si.sizeDoneLabel = newtLabel(29, 10, ""); si.sizeRemainsLabel = newtLabel(29, 11, ""); si.timeTotalLabel = newtLabel(42, 9, ""); si.timeDoneLabel = newtLabel(42, 10, ""); si.timeRemainsLabel = newtLabel(42, 11, ""); si.globalScale = newtScale(1, 13, 58, sizePackages); newtFormAddComponents(si.form, si.packageLabel, si.sizeLabel, si.summaryText, si.pkgScale, si.globalScale, si.pkgDoneLabel, si.pkgRemainsLabel, si.sizeDoneLabel, si.sizeRemainsLabel, si.timeDoneLabel, si.timeRemainsLabel, si.timeTotalLabel, NULL); } static void swPackage(Header h) { char * name, * version, * release, * summary; char buf[50]; uint_32 * size; headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL); headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL); headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL); headerGetEntry(h, RPMTAG_SIZE, NULL, (void *) &size, NULL); if (!headerGetEntry(h, RPMTAG_SUMMARY, NULL, (void *) &summary, NULL)) summary = _("(no summary)"); sprintf(buf, "%s-%s-%s", name, version, release); newtLabelSetText(si.packageLabel, buf); sprintf(buf, "%dk", (*size) / 1024); newtLabelSetText(si.sizeLabel, buf); newtTextboxSetText(si.summaryText, summary); si.thisPackageSize = *size; newtScaleSet(si.pkgScale, 0); newtDrawForm(si.form); newtRefresh(); } static void swPackageComplete(void) { char buf[50]; time_t now, finishTime, elapsedTime, remainingTime; si.packagesDone++; si.sizeDone += si.thisPackageSize; sprintf(buf, "%8d", si.packagesDone); newtLabelSetText(si.pkgDoneLabel, buf); sprintf(buf, "%8d", si.numPackages - si.packagesDone); newtLabelSetText(si.pkgRemainsLabel, buf); sprintf(buf, "%4dM", si.sizeDone / (1024 * 1024)); newtLabelSetText(si.sizeDoneLabel, buf); sprintf(buf, "%4dM", (si.sizePackages - si.sizeDone) / (1024 * 1024)); newtLabelSetText(si.sizeRemainsLabel, buf); now = time(NULL); elapsedTime = now - si.timeStarted; formatTime(buf, elapsedTime); newtLabelSetText(si.timeDoneLabel, buf); finishTime = (((float) si.sizePackages) / si.sizeDone) * elapsedTime; formatTime(buf, finishTime); newtLabelSetText(si.timeTotalLabel, buf); remainingTime = finishTime - elapsedTime; formatTime(buf, remainingTime); newtLabelSetText(si.timeRemainsLabel, buf); newtScaleSet(si.globalScale, si.sizeDone); newtRefresh(); } static void swCallback(const unsigned long amount, const unsigned long total) { if (total == 0) newtScaleSet(si.pkgScale, 100); else newtScaleSet(si.pkgScale, (amount * 100) / total); newtRefresh(); } static void swClose(void) { newtPopWindow(); } static void formatTime(char * buf, time_t t) { int hours, minutes, secs; hours = t / 60 / 60; t %= (60 * 60); minutes = t / 60; t %= 60; secs = t; sprintf(buf, "%01d:%02d.%02d", hours, minutes, secs); }