home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / doit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-11  |  14.0 KB  |  524 lines

  1. #include <errno.h>
  2. #include <fcntl.h>
  3. #include <newt.h>
  4. #include <rpmlib.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>        /* for mkdir(2) ?!? */
  8. #include <sys/time.h>
  9. #include <sys/wait.h>
  10. #include <sys/mount.h>
  11. #include <unistd.h>
  12. #include <popt.h>
  13.  
  14. #include "config.h"
  15. #include "doit.h"
  16. #include "install.h"
  17. #include "intl.h"
  18. #include "kbd.h"
  19. #include "kickstart.h"
  20. #include "log.h"
  21. #include "syslog.h"
  22. #include "windows.h"
  23.  
  24.  
  25. extern int testing;
  26. FILE * logFile = NULL;
  27.  
  28. static int installPackage(rpmdb db, char * rootPath,
  29.               struct installMethod * method, 
  30.               struct packageInfo * pkg,
  31.               int errfd, int flags);
  32. static void setupXfree(struct installMethod * method, rpmdb db, 
  33.                char * rootPath, struct pkgSet * psp, int errfd);
  34. static void rpmerror(void);
  35.  
  36. static void swOpen(int numPackages, int sizePackages);
  37. static void swPackage(Header h);
  38. static void swPackageComplete();
  39. static void swClose(void);
  40. static void swCallback(const unsigned long amount, const unsigned long total);
  41. static void formatTime(char * buf, time_t t);
  42.  
  43. int doInstall(struct installMethod * method, char * rootPath,
  44.           struct pkgSet * psp, char * netSharedPath, char * keymap,
  45.           int upgrade) {
  46.     int i, totalNumPackages, totalSizePackages;
  47.     struct packageInfo ** orderedPackages;
  48.     int flags = 0;
  49.     rpmdb db;
  50.     int errfd;
  51.     char * logFileName = "/dev/tty5";
  52.     char * path;
  53.     rpmDependencies rpmdeps, rpmorder;
  54.     char * hostEntry = 
  55.         "127.0.0.1        localhost localhost.localdomain\n";
  56.     int fd;
  57.  
  58.     if (testing) return 0;
  59.  
  60.     path = alloca(strlen(rootPath) + 20);
  61.  
  62.     fd = open(".", O_RDONLY);
  63.     chdir(rootPath);
  64.     mkdir("dev", 0755);
  65.     mkdir("etc", 0755);
  66.     mkdir("tmp", 0755);
  67.     mkdir("var", 0755);
  68.     mkdir("var/tmp", 0755);
  69.     mkdir("var/lib", 0755);
  70.     mkdir("var/lib/rpm", 0755);
  71.     fchdir(fd);
  72.     close(fd);
  73.  
  74.     #ifdef __sparc__
  75.     logMessage("removing /mnt/usr/X11R6 symlink");
  76.     unlink("/mnt/usr/X11R6");
  77.     #endif
  78.  
  79.     handleSyslogSocket(rootPath);
  80.  
  81.     if (!upgrade) {
  82.     sprintf(path, "%s/etc/hosts", rootPath);
  83.     fd = open(path, O_CREAT | O_RDWR, 0644);
  84.     if (fd < 0) {
  85.         errorWindow("Failed to create etc/hosts: %s.");
  86.         return INST_ERROR;
  87.     }
  88.  
  89.     write(fd, hostEntry, strlen(hostEntry));
  90.     close(fd);
  91.     }
  92.  
  93.     sprintf(path, "%s/tmp/%s.log", rootPath, upgrade ? "upgrade" : "install");
  94.     if (upgrade) 
  95.     flags |= RPMINSTALL_UPGRADE | RPMINSTALL_REPLACEFILES;
  96.     logFile = fopen(path, "w");
  97.     if (logFile) {
  98.     setlinebuf(logFile);
  99.     logMessage("opened %s", path);
  100.     } else {
  101.     logMessage("failed to open %s :-(", path);
  102.     newtWinMessage(_("Error"), _("Ok"),
  103.         _("Failed to open %s. No upgrade log will be kept."), path);
  104.     }
  105.  
  106.     errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
  107.     if (errfd < 0) {
  108.     logMessage("failed to open /dev/tty5!");
  109.     logFileName = "/tmp/exec.log";
  110.     errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
  111.     if (errfd < 0) {
  112.         logMessage("failed to open %s: %s!\n", logFileName, 
  113.             strerror(errno));
  114.         errfd = 2;
  115.     }
  116.     }
  117.  
  118.     rpmErrorSetCallback(rpmerror);
  119.  
  120.     /* FIXME: we ought to read /mnt/us/lib/rpmrc if we're in the midst of an
  121.        upgrade, but it's not obvious how to get RPM to do that. */
  122.     rpmSetVar(RPMVAR_NETSHAREDPATH, netSharedPath);
  123.  
  124.     if (rpmdbOpen(rootPath, &db, O_RDWR | O_CREAT, 0644)) {
  125.     errorWindow(_("Fatal error opening RPM database"));
  126.     return INST_ERROR;
  127.     }
  128.     logMessage("opened rpm database");
  129.  
  130.     rpmdeps = rpmdepDependencies(db);
  131.     rpmorder = rpmdepDependencies(NULL);
  132.  
  133.     for (i = 0; i < psp->numPackages; i++) {
  134.     if (!strcmp(psp->packages[i]->name, "basesystem")) {
  135.         rpmdepAddPackage(rpmdeps, psp->packages[i]->h, psp->packages[i]);
  136.         rpmdepAddPackage(rpmorder, psp->packages[i]->h, psp->packages[i]);
  137.     }
  138.     }
  139.  
  140.     totalNumPackages = 0, totalSizePackages = 0;
  141.     for (i = 0; i < psp->numPackages; i++) {
  142.     if (psp->packages[i]->selected) {
  143.         if (strcmp(psp->packages[i]->name, "basesystem")) {
  144.         rpmdepAddPackage(rpmdeps, psp->packages[i]->h, 
  145.                  psp->packages[i]);
  146.         rpmdepAddPackage(rpmorder, psp->packages[i]->h, 
  147.                  psp->packages[i]);
  148.         }
  149.  
  150.         totalSizePackages += psp->packages[i]->size;
  151.         totalNumPackages++;
  152.     }
  153.     }
  154.  
  155.     if (rpmdepOrder(rpmorder, (void ***) &orderedPackages)) {
  156.     rpmdbClose(db);
  157.     newtWinMessage(_("Error"), _("Ok"), 
  158.             _("Error ordering package list: %s"), rpmErrorString());
  159.     close(errfd);
  160.     return 1;
  161.     }
  162.  
  163.     rpmdepDone(rpmdeps);
  164.     rpmdepDone(rpmorder);
  165.  
  166.     if (testing) {
  167.     newtWinMessage("Status", "Ok", "Packages would be installed now");
  168.     return 0;
  169.     }
  170.  
  171.     swOpen(totalNumPackages, totalSizePackages);
  172.  
  173.     logMessage("installing %d packages", totalNumPackages);
  174.     for (i = 0; i < totalNumPackages; i++) {
  175.     installPackage(db, rootPath, method, orderedPackages[i], errfd, flags);
  176.     }
  177.     swClose();
  178.  
  179.     free(orderedPackages);
  180.  
  181.     #ifndef __sparc__
  182.     if (!upgrade) {
  183.     sprintf(path, "%s/etc/sysconfig", rootPath);
  184.     mkdir(path, 0755);
  185.     writeKbdConfig(path, keymap);
  186.     }
  187.     #endif
  188.  
  189.     if (!upgrade) {
  190.     mouseConfig(rootPath);
  191.     writeLangInfo(rootPath);
  192.         setupXfree(method, db, rootPath, psp, errfd);
  193.     }
  194.  
  195.     rpmdbClose(db);
  196.     close(errfd);
  197.  
  198.     #ifdef __sparc__
  199.     logMessage("making /etc/X11/X symlink");
  200.     symlink("../../usr/X11R6/bin/Xsun", "/mnt/etc/X11/X");
  201.     #endif
  202.  
  203.     if (logFile) fclose(logFile);
  204.  
  205.     logMessage("rpm database closed");
  206.  
  207.     return 0;
  208. }
  209.  
  210. static int installPackage(rpmdb db, char * rootPath, 
  211.               struct installMethod * method, 
  212.               struct packageInfo * pkg,
  213.               int errfd, int flags) {
  214.     int fd, olderr;
  215.     char * realName;
  216.     int olderrno, rc;
  217.  
  218.     if (logFile)
  219.     fprintf(logFile, "%s %s.\n", 
  220.         (flags & RPMINSTALL_UPGRADE) ? 
  221.             _("Upgrading") : _("Installing"), pkg->name);
  222.  
  223.     swPackage(pkg->h);
  224.  
  225.     if (method->getFile(method, pkg->data, &realName)) {
  226.     logMessage("getFile method failed for %s", pkg->data);
  227.     if (logFile)
  228.         fprintf(logFile, "Failed to get file for package %s.\n", pkg->name);
  229.     swPackageComplete();
  230.     return 1;
  231.     }
  232.  
  233.     fd = open(realName, O_RDONLY);
  234.     if (fd < 0) {
  235.     olderrno = errno;
  236.     logMessage("cannot open RPM file %s: %s", pkg->data,
  237.             strerror(olderrno));
  238.     newtWinMessage(_("Error"), _("Ok"), 
  239.             _("Error installing package: cannot open RPM file "
  240.             "for %s: %s"), pkg->data, strerror(errno));
  241.     if (logFile)
  242.         fprintf(logFile, "\tcannot open RPM file %s: %s\n", 
  243.             (char *) pkg->data, strerror(olderrno));
  244.  
  245.     swPackageComplete();
  246.  
  247.     return 1;
  248.     }
  249.  
  250.     /* this is a hack */
  251.     if (!strcmp(pkg->name, "lilo") || !strcmp(pkg->name, "kernel"))
  252.     flags |= RPMINSTALL_NOSCRIPTS;
  253.  
  254.     olderr = dup(2);
  255.     dup2(errfd, 2);
  256.     rc = rpmInstallPackage(rootPath, db, fd, NULL, 
  257.         flags | RPMINSTALL_REPLACEPKG | RPMINSTALL_REPLACEFILES, 
  258.             swCallback, NULL);
  259.     dup2(olderr, 2);
  260.     close(olderr);
  261.  
  262.     if (rc) {
  263.     olderrno = errno;
  264.     logMessage("Error installing package: package install of "
  265.             "%s failed: %s", pkg->name, rpmErrorString());
  266.     newtWinMessage(_("Error"), _("Ok"), 
  267.             _("RPM install of %s failed: %s"), pkg->name,
  268.             rpmErrorString());
  269.     if (logFile)
  270.         fprintf(logFile, "\tcannot open RPM file %s: %s\n", 
  271.             (char *) pkg->data, strerror(olderrno));
  272.     } 
  273.  
  274.     close(fd);
  275.     swPackageComplete();
  276.  
  277.     if (method->rmFiles) unlink(realName);
  278.  
  279.     return 0;
  280. }
  281.  
  282. static void setupXfree(struct installMethod * method, rpmdb db, 
  283.                char * rootPath,
  284.                struct pkgSet * psp, int errfd) {
  285.     int fd, i;
  286.     char buf[200], * chptr;
  287.     char server[50];
  288.     int rc;
  289.     char * path;
  290.     char * procPath;
  291.  
  292.     path = alloca(strlen(rootPath) + 200);
  293.     procPath = alloca(strlen(rootPath) + 50);
  294.     sprintf(path, "%s/usr/X11R6/bin/Xconfigurator", rootPath);
  295.  
  296.     /* This is a cheap trick to see if our X component was installed */
  297.     if (access(path, X_OK)) {
  298.     logMessage("%s cannot be run", path);
  299.     return;
  300.     }
  301.  
  302.     /* need proc to do pci probing */
  303.     sprintf(procPath, "%s/proc", rootPath);
  304.     if ((rc = doMount("/proc", procPath, "proc", 0, 0))) {
  305.     return;
  306.     }
  307.  
  308.     /* this handles kickstart and normal/expert modes */
  309.     if ((rc=xfree86Config(rootPath, "--pick")))
  310.     return;
  311.     
  312.     sprintf(path, "%s/tmp/SERVER", rootPath);
  313.     if ((fd = open(path, O_RDONLY)) < 0) {
  314.     logMessage("failed to open %s: %s", path, strerror(errno));
  315.     return;
  316.     }
  317.  
  318.     buf[0] = '\0';
  319.     read(fd, buf, sizeof(buf));
  320.     close(fd);
  321.     chptr = buf;
  322.     while (chptr < (buf + sizeof(buf) - 1) && *chptr && *chptr != ' ')
  323.     chptr++;
  324.  
  325.     if (chptr >= (buf + sizeof(buf) - 1) || *chptr != ' ') {
  326.     logMessage("couldn't find ' ' in %s", path);
  327.     return;
  328.     }
  329.  
  330.     *chptr = '\0';
  331.     strcpy(server, "XFree86-");
  332.     strcat(server, buf);
  333.  
  334.     logMessage("I will install the %s package", server);
  335.  
  336.     for (i = 0; i < psp->numPackages; i++) {
  337.     if (!strcmp(psp->packages[i]->name, server)) {
  338.         logMessage("\tfound package: %s", psp->packages[i]->name);
  339.         swOpen(1, psp->packages[i]->size);
  340.         installPackage(db, rootPath, method, psp->packages[i], errfd, 0);
  341.         swClose();
  342.         break;
  343.     }
  344.     }
  345.  
  346.     /* this handles kickstart and normal/expert modes */
  347.     if ((rc=xfree86Config(rootPath, "--continue")))
  348.     return;
  349.  
  350.     /* done with proc now */
  351.     umount(procPath);
  352. }
  353.  
  354. static void rpmerror(void) {
  355.     int code;
  356.  
  357.     code = rpmErrorCode();
  358.     if (code != RPMERR_UNLINK && code != RPMERR_RMDIR) {
  359.     if (logFile)
  360.         fprintf(logFile, "%s\n", rpmErrorString());
  361.     else
  362.         logMessage(rpmErrorString());
  363.     }
  364. }
  365.  
  366. static struct statusWindowInfo {
  367.     newtComponent form, packageLabel, sizeLabel, summaryText;
  368.     newtComponent pkgScale, globalScale;
  369.     newtComponent pkgDoneLabel, pkgRemainsLabel;
  370.     newtComponent sizeDoneLabel, sizeRemainsLabel;
  371.     newtComponent timeDoneLabel, timeRemainsLabel, timeTotalLabel;
  372.     int numPackages, packagesDone;
  373.     unsigned int sizePackages, sizeDone;
  374.     int thisPackageSize;
  375.     time_t timeStarted;
  376. } si;
  377.  
  378. static void swOpen(int numPackages, int sizePackages) {
  379.     char buf[50];
  380.  
  381.     newtCenteredWindow(60, 15, _("Install Status"));
  382.  
  383.     si.form = newtForm(NULL, NULL, 0);
  384.     newtFormAddComponent(si.form, newtLabel(1, 1, "Package:"));
  385.     newtFormAddComponent(si.form, newtLabel(1, 2, "Size   :"));
  386.     newtFormAddComponent(si.form, newtLabel(1, 3, "Summary:"));
  387.  
  388.     si.packageLabel = newtLabel(13, 1, "");
  389.     si.sizeLabel    = newtLabel(13, 2, "");
  390.     si.summaryText  = newtTextbox(13, 3, 45, 2, NEWT_TEXTBOX_WRAP);
  391.  
  392.     si.pkgScale = newtScale(3, 6, 54, 100);
  393.  
  394.     newtFormAddComponent(si.form, 
  395.     newtLabel(1, 8, "             Packages       Bytes           Time"));
  396.     /*         12345678901234567890123456789012345678901234567
  397.                   1         2         3         4 */
  398.     newtFormAddComponent(si.form, newtLabel(1, 9,  "Total     :"));
  399.     newtFormAddComponent(si.form, newtLabel(1, 10, "Completed :"));
  400.     newtFormAddComponent(si.form, newtLabel(1, 11, "Remaining :"));
  401.  
  402.     si.numPackages = numPackages;
  403.     si.sizePackages = sizePackages;
  404.     si.packagesDone = 0;
  405.     si.sizeDone = 0;
  406.     si.timeStarted = time(NULL);
  407.  
  408.     sprintf(buf, "%8d", numPackages);
  409.     newtFormAddComponent(si.form, newtLabel(14, 9, buf));
  410.     si.pkgDoneLabel = newtLabel(14, 10, "");
  411.     si.pkgRemainsLabel = newtLabel(14, 11, "");
  412.  
  413.     sprintf(buf, "%4uM", sizePackages / (1024 * 1024));
  414.     newtFormAddComponent(si.form, newtLabel(29, 9, buf));
  415.     si.sizeDoneLabel = newtLabel(29, 10, "");
  416.     si.sizeRemainsLabel = newtLabel(29, 11, "");
  417.  
  418.     si.timeTotalLabel = newtLabel(42, 9, "");
  419.     si.timeDoneLabel = newtLabel(42, 10, "");
  420.     si.timeRemainsLabel = newtLabel(42, 11, "");
  421.  
  422.     si.globalScale = newtScale(1, 13, 58, sizePackages);
  423.  
  424.     newtFormAddComponents(si.form, si.packageLabel, si.sizeLabel, 
  425.               si.summaryText, si.pkgScale, si.globalScale, 
  426.               si.pkgDoneLabel, si.pkgRemainsLabel, 
  427.               si.sizeDoneLabel, si.sizeRemainsLabel, 
  428.               si.timeDoneLabel, si.timeRemainsLabel,
  429.               si.timeTotalLabel, NULL);
  430. }
  431.  
  432. static void swPackage(Header h) {
  433.     char * name, * version, * release, * summary;
  434.     char buf[50];
  435.     uint_32 * size;
  436.  
  437.     headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL);
  438.     headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL);
  439.     headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL);
  440.     headerGetEntry(h, RPMTAG_SIZE, NULL, (void *) &size, NULL);
  441.  
  442.     if (!headerGetEntry(h, RPMTAG_SUMMARY, NULL, (void *) &summary, NULL))
  443.     summary = _("(no summary)");
  444.  
  445.     sprintf(buf, "%s-%s-%s", name, version, release);
  446.     newtLabelSetText(si.packageLabel, buf);
  447.  
  448.     sprintf(buf, "%dk", (*size) / 1024);
  449.     newtLabelSetText(si.sizeLabel, buf);
  450.  
  451.     newtTextboxSetText(si.summaryText, summary);
  452.  
  453.     si.thisPackageSize = *size;
  454.  
  455.     newtScaleSet(si.pkgScale, 0);
  456.  
  457.     newtDrawForm(si.form);
  458.     newtRefresh();
  459. }
  460.  
  461. static void swPackageComplete(void) {
  462.     char buf[50];
  463.     time_t now, finishTime, elapsedTime, remainingTime;
  464.  
  465.     si.packagesDone++;
  466.     si.sizeDone += si.thisPackageSize;
  467.  
  468.     sprintf(buf, "%8d", si.packagesDone);
  469.     newtLabelSetText(si.pkgDoneLabel, buf);
  470.  
  471.     sprintf(buf, "%8d", si.numPackages - si.packagesDone);
  472.     newtLabelSetText(si.pkgRemainsLabel, buf);
  473.  
  474.     sprintf(buf, "%4dM", si.sizeDone / (1024 * 1024));
  475.     newtLabelSetText(si.sizeDoneLabel, buf);
  476.  
  477.     sprintf(buf, "%4dM", (si.sizePackages - si.sizeDone) / (1024 * 1024));
  478.     newtLabelSetText(si.sizeRemainsLabel, buf);
  479.  
  480.     now = time(NULL);
  481.     elapsedTime = now - si.timeStarted;
  482.     formatTime(buf, elapsedTime);
  483.     newtLabelSetText(si.timeDoneLabel, buf);
  484.  
  485.     finishTime = (((float) si.sizePackages) / si.sizeDone) * elapsedTime;
  486.     formatTime(buf, finishTime);
  487.     newtLabelSetText(si.timeTotalLabel, buf);
  488.     
  489.     remainingTime = finishTime - elapsedTime;
  490.     formatTime(buf, remainingTime);
  491.     newtLabelSetText(si.timeRemainsLabel, buf);
  492.  
  493.     newtScaleSet(si.globalScale, si.sizeDone);
  494.  
  495.     newtRefresh();
  496. }
  497.  
  498. static void swCallback(const unsigned long amount, const unsigned long total) {
  499.     if (total == 0)
  500.     newtScaleSet(si.pkgScale, 100);
  501.     else
  502.     newtScaleSet(si.pkgScale, (amount * 100) / total);
  503.  
  504.     newtRefresh();
  505. }
  506.  
  507. static void swClose(void) {
  508.     newtPopWindow();
  509. }
  510.  
  511. static void formatTime(char * buf, time_t t) {
  512.     int hours, minutes, secs;
  513.  
  514.     hours = t / 60 / 60;
  515.     t %= (60 * 60);
  516.  
  517.     minutes = t / 60;
  518.     t %= 60;
  519.  
  520.     secs = t;
  521.  
  522.     sprintf(buf, "%01d:%02d.%02d", hours, minutes, secs);
  523. }
  524.