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

  1. #include <ctype.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <newt.h>
  5. #include <popt.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/mount.h>
  10. #include <unistd.h>
  11.  
  12. #include "dns.h"
  13. #include "fs.h"
  14. #include "hd.h"
  15. #include "intl.h"
  16. #include "install.h"
  17. #include "kickstart.h"
  18. #include "log.h"
  19. #include "methods.h"
  20. #include "net.h"
  21. #include "windows.h"
  22.  
  23. /* This was split into two pieces to keep the initial install program small */
  24.  
  25. static int nfsPrepare(struct installMethod * method, struct netInfo * netc,
  26.                struct intfInfo * intf, int forceSupp,
  27.                struct driversLoaded ** dl);
  28. static int cdromPrepare(struct installMethod * method, struct netInfo * netc,
  29.                struct intfInfo * intf, int forceSupp,
  30.                struct driversLoaded ** dl);
  31. static int nfsGetSetup(char ** hostptr, char ** dirptr);
  32. int floppyRoot(struct installMethod * method, struct netInfo * netc,
  33.                struct intfInfo * intf, int forceSupp,
  34.                struct driversLoaded ** dl);
  35. static int totalMemory(void);            /* in K */
  36.  
  37. #define CDROM_METHOD_NUM 0
  38. #define NFS_METHOD_NUM 1
  39. /* We have a loop a bit later which translates the 'Local CDROM' language */
  40. static struct installMethod methods[] = {
  41.     { "Local CDROM",         "cdrom", 0, cdromPrepare, NULL, NULL,
  42.         NULL, NULL, NULL },
  43.     { "NFS image",         "nfs", 0, nfsPrepare, NULL, NULL,
  44.         NULL, NULL, NULL },
  45.     { "hard drive",        "hd", 0, floppyRoot, NULL, NULL,
  46.         NULL, NULL, NULL },
  47.     { "FTP",             "ftp", 0, floppyRoot, NULL, NULL,
  48.         NULL, NULL, NULL },
  49. #ifdef __i386__
  50.     { "SMB image",         "smb", 0, floppyRoot, NULL, NULL,
  51.         NULL, NULL, NULL },
  52. #endif
  53. #if 0
  54.     { "SCSI Tape Install",     "tape", 0, floppyRoot, NULL, NULL,
  55.         NULL, NULL, NULL },
  56. #endif
  57. } ;
  58. static int numMethods = sizeof(methods) / sizeof(struct installMethod);
  59. static int isMounted = 0;
  60.  
  61. #define LOAD_BLOCK_COUNT 16
  62. static int loadRamdisk(char * todev, char * fromdev, int blocks,
  63.             char * label) {
  64.     newtComponent form, scale;
  65.     char * topath, * frompath;
  66.     char buf[LOAD_BLOCK_COUNT * 1024];
  67.     int rc = 0;
  68.     int i;
  69.     int to, from;
  70.  
  71.     if (blocks % LOAD_BLOCK_COUNT) {
  72.     logMessage("internal error: blocks in loadRamdisk() must be "
  73.         "divisible by %d!!", LOAD_BLOCK_COUNT);
  74.     return 1;
  75.     }
  76.  
  77.     topath = alloca(strlen(todev) + 8);
  78.     sprintf(topath, "/tmp/%s", todev);
  79.  
  80.     frompath = alloca(strlen(fromdev) + 8);
  81.     sprintf(frompath, "/tmp/%s", fromdev);
  82.  
  83.     if (devMakeInode(todev, topath)) return 1;
  84.     if (devMakeInode(fromdev, frompath)) {
  85.     unlink(topath);
  86.     return 1;
  87.     }
  88.  
  89.     to = open(topath, O_WRONLY);
  90.     if (to < 0) {
  91.     logMessage("failed to open %s: %s", topath, strerror(errno));
  92.     unlink(topath);
  93.     unlink(frompath);
  94.     return 1;
  95.     }
  96.  
  97.     from = open(frompath, O_RDONLY);
  98.     if (from < 0) {
  99.     logMessage("failed to open %s: %s", frompath, strerror(errno));
  100.     unlink(topath);
  101.     unlink(frompath);
  102.     return 1;
  103.     }
  104.  
  105.     unlink(frompath);
  106.     unlink(topath);
  107.  
  108.     logMessage("copying %d blocks from %s to %s", blocks, fromdev, todev);
  109.  
  110.     newtCenteredWindow(60, 5, "Loading");
  111.     
  112.     form = newtForm(NULL, NULL, 0);
  113.     
  114.     newtFormAddComponent(form, newtLabel(1, 1, label));
  115.     scale = newtScale(1, 3, 58, blocks / LOAD_BLOCK_COUNT);
  116.     newtFormAddComponent(form, scale);
  117.     newtDrawForm(form);
  118.     newtRefresh();
  119.  
  120.     for (i = 0; i < (blocks / LOAD_BLOCK_COUNT) && !rc; i++) {
  121.     newtScaleSet(scale, i);
  122.     newtRefresh();
  123.  
  124.     if (read(from, buf, sizeof(buf)) != sizeof(buf)) {
  125.         logMessage("error reading from device: %s", strerror(errno));
  126.         rc = 1;
  127.     } else {
  128.         if (write(to, buf, sizeof(buf)) != sizeof(buf)) {
  129.         logMessage("error writing to device: %s", strerror(errno));
  130.         rc = 1;
  131.         }
  132.     }
  133.     }
  134.  
  135.     newtPopWindow();
  136.     newtFormDestroy(form);
  137.     
  138.     close(from);
  139.     close(to);
  140.  
  141.     return rc;
  142. }
  143.  
  144. static int totalMemory(void) {
  145.     int fd;
  146.     int bytesRead;
  147.     char buf[4096];
  148.     char * chptr, * start;
  149.     int total = 0;
  150.  
  151.     fd = open("/proc/meminfo", O_RDONLY);
  152.     if (fd < 0) {
  153.     logMessage("failed to open /proc/meminfo: %s", strerror(errno));
  154.     return 0;
  155.     }
  156.  
  157.     bytesRead = read(fd, buf, sizeof(buf) - 1);
  158.     if (bytesRead < 0) {
  159.     logMessage("failed to read from /proc/meminfo: %s", strerror(errno));
  160.     close(fd);
  161.     return 0;
  162.     }
  163.  
  164.     close(fd);
  165.     buf[bytesRead] = '\0';
  166.  
  167.     chptr = buf;
  168.     while (*chptr && !total) {
  169.     if (*chptr != '\n' || strncmp(chptr + 1, "MemTotal:", 9)) {
  170.         chptr++;
  171.         continue;
  172.     }
  173.  
  174.     start = ++chptr ;
  175.     while (*chptr && *chptr != '\n') chptr++;
  176.  
  177.     *chptr = '\0';
  178.  
  179.     logMessage("found total memory tag: \"%s\"", start);
  180.     
  181.     while (!isdigit(*start) && *start) start++;
  182.     if (!*start) {
  183.         logMessage("no number appears after MemTotal tag");
  184.         return 0;
  185.     }
  186.  
  187.     chptr = start;
  188.     while (*chptr && isdigit(*chptr)) {
  189.         total = (total * 10) + (*chptr - '0');
  190.         chptr++;
  191.     }
  192.     }
  193.  
  194.     logMessage("%d kB are available", total);
  195.  
  196.     return total;
  197. }
  198.  
  199. static int installMethodWindow(struct installMethod ** method,
  200.                    int showSuppBox,
  201.                    int * forceSuppPtr) {
  202.     int i;
  203.     newtComponent textbox, listbox, form, okay, back, result;
  204.     newtGrid buttonBar, grid, middle;
  205.     char forceSupp = showSuppBox ? '*' : ' ';
  206.  
  207.     textbox = newtTextboxReflowed(-1, -1, _("What type of media contains "
  208.                   "the packages to be installed?"), 30, 10, 
  209.                   0, 0);
  210.  
  211.     listbox = newtListbox(-1, -1, numMethods, NEWT_FLAG_RETURNEXIT);
  212.  
  213.     for (i = 0; i < numMethods; i++) {
  214.     newtListboxAddEntry(listbox, _(methods[i].name), methods + i);
  215.     }
  216.  
  217.     buttonBar = newtButtonBar(_("Ok"), &okay, _("Back"), &back, NULL);
  218.     
  219.     middle = newtCreateGrid(1, 2);
  220.     newtGridSetField(middle, 0, 0, NEWT_GRID_COMPONENT, listbox,
  221.              0, 0, 0, 0, 0, 0);
  222.  
  223. #ifdef __i386__
  224.     if (expert || showSuppBox)
  225.     newtGridSetField(middle, 0, 1, NEWT_GRID_COMPONENT,
  226.                 newtCheckbox(-1, -1, _("Force supplemental disk"),
  227.                          forceSupp, NULL, &forceSupp),
  228.              0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0);
  229. #endif
  230.  
  231.     grid = newtGridBasicWindow(textbox, middle, buttonBar);
  232.     newtGridWrappedWindow(grid, _("Installation Method"));
  233.  
  234.     form = newtForm(NULL, 0, 0);
  235.     newtGridAddComponentsToForm(grid, form, 1);
  236.     newtGridFree(grid, 1);
  237.  
  238.     result = newtRunForm(form);
  239.     newtPopWindow();
  240.     if (result == back) {
  241.     newtFormDestroy(form);
  242.     return INST_CANCEL;
  243.     }
  244.  
  245.     *method = newtListboxGetCurrent(listbox);
  246.     newtFormDestroy(form);
  247.  
  248.     *forceSuppPtr = (forceSupp != ' ');
  249.  
  250.     return 0;
  251. }
  252.  
  253. int chooseInstallMethod(int showSuppBox, struct installMethod ** method, 
  254.             struct netInfo * netc, struct intfInfo * intf, 
  255.             struct driversLoaded ** dl) {
  256.     int rc;
  257.     int forceSupp = 0;
  258.  
  259.     if (kickstart) {
  260.     if (!ksGetCommand(KS_CMD_NFS, NULL, NULL, NULL)) {
  261.         *method = methods + NFS_METHOD_NUM;
  262.         return (*method)->prepareImage((*method), netc, intf, 0, dl);
  263.     } else if (!ksGetCommand(KS_CMD_CDROM, NULL, NULL, NULL)) {
  264.         *method = methods + CDROM_METHOD_NUM;
  265.         return (*method)->prepareImage((*method), netc, intf, 0, dl);
  266.     } else {
  267.         logMessage("No kickstart method was specified.");
  268.         kickstart = 0;
  269.     }
  270.     }
  271.  
  272.     do {
  273.     rc = installMethodWindow(method, showSuppBox, &forceSupp);
  274.     if (rc) return rc;
  275.  
  276.     if ((*method)->prepareImage) {
  277.         rc = (*method)->prepareImage((*method), netc, intf, forceSupp, dl);
  278.         if (rc == INST_ERROR) return rc;
  279.     }
  280.     } while (rc);
  281.  
  282.     return 0;
  283. }
  284.  
  285. /* We could use newtWinEntries() here, if we didn't like those clever
  286.    callbacks */
  287. static int nfsGetSetup(char ** hostptr, char ** dirptr) {
  288.     newtComponent form, okay, cancel, answer, text;
  289.     newtComponent siteLabel, dirLabel;
  290.     newtGrid buttons, entryArea, grid;
  291.     struct nfsMountCallbackInfo cbInfo;
  292.     char * reflowedText;
  293.     int width, height;
  294.  
  295.     if (*hostptr) {
  296.     cbInfo.serverVal = *hostptr;
  297.     cbInfo.netpathVal = *dirptr;
  298.     } else {
  299.     cbInfo.serverVal = "";
  300.     cbInfo.netpathVal = "";
  301.     }
  302.  
  303.     form = newtForm(NULL, NULL, 0);
  304.     buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL);
  305.  
  306.     reflowedText = newtReflowText(
  307.                _("Please enter the following information:\n"
  308.                  "\n"
  309.                  "    o the name or IP number of your NFS server\n"
  310.                  "    o the directory on that server containing\n"
  311.                  "      Red Hat Linux for your architecture"),
  312.              60, 10, 10, &width, &height);
  313.     text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
  314.     newtTextboxSetText(text, reflowedText);
  315.  
  316.     free(reflowedText);
  317.  
  318.     entryArea = newtCreateGrid(2, 2);
  319.     siteLabel = newtLabel(-1, -1, _("NFS server name:"));
  320.     newtGridSetField(entryArea, 0, 0, NEWT_GRID_COMPONENT, siteLabel, 
  321.             0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
  322.     dirLabel = newtLabel(-1, -1, _("Red Hat directory:"));
  323.     newtGridSetField(entryArea, 0, 1, NEWT_GRID_COMPONENT, dirLabel, 
  324.             0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0);
  325.  
  326.     cbInfo.server = newtEntry(-1, -1, cbInfo.serverVal, 24, &cbInfo.serverVal, 
  327.                 NEWT_ENTRY_SCROLL);
  328.     newtComponentAddCallback(cbInfo.server, nfsMountCallback, &cbInfo);
  329.     cbInfo.netpath = newtEntry(-1, -1, cbInfo.netpathVal, 24, 
  330.                 &cbInfo.netpathVal, NEWT_ENTRY_SCROLL);
  331.     cbInfo.mntpoint = NULL;
  332.  
  333.     newtGridSetField(entryArea, 1, 0, NEWT_GRID_COMPONENT, cbInfo.server, 
  334.             1, 0, 0, 0, 0, 0);
  335.     newtGridSetField(entryArea, 1, 1, NEWT_GRID_COMPONENT, cbInfo.netpath, 
  336.             1, 0, 0, 0, 0, 0);
  337.  
  338.     grid = newtCreateGrid(1, 3);
  339.     newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
  340.             0, 0, 0, 0, 0, 0);
  341.     newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryArea,
  342.             0, 1, 0, 1, 0, 0);
  343.     newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
  344.             0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
  345.  
  346.     newtGridWrappedWindow(grid, _("NFS Setup"));
  347.  
  348.     newtGridFree(grid, 1);
  349.  
  350.     newtFormAddComponents(form, text, cbInfo.server, cbInfo.netpath, okay, 
  351.               cancel, dirLabel, siteLabel, NULL);
  352.  
  353.     answer = newtRunForm(form);
  354.     if (answer == cancel) {
  355.     newtFormDestroy(form);
  356.     newtPopWindow();
  357.     
  358.     return INST_CANCEL;
  359.     }
  360.  
  361.     if (*hostptr) free(*hostptr);
  362.     if (*dirptr) free(*dirptr);
  363.     *hostptr = strdup(cbInfo.serverVal);
  364.     *dirptr = strdup(cbInfo.netpathVal);
  365.  
  366.     newtFormDestroy(form);
  367.     newtPopWindow();
  368.  
  369.     return 0;
  370. }
  371.  
  372. static int cdromPrepare(struct installMethod * method, struct netInfo * netc,
  373.                 struct intfInfo * intf, int useSupp, 
  374.             struct driversLoaded ** dl) {
  375.     char * cddev;
  376.     int rc;
  377.  
  378.     if (!kickstart)
  379.     rc = newtWinChoice(_("Note"), _("Ok"), ("Back"),
  380.             _("Insert your Red Hat CD into your CD drive now"));
  381.  
  382.     if (rc == 2) return INST_CANCEL;
  383.  
  384.     while (1) {
  385.     /* this autoprobes already, so we don't need to do anything special
  386.        for the kickstart :-) */
  387.     rc = setupCDdevice(&cddev, dl);
  388.     if (rc) return rc;
  389.  
  390.     if ((rc = loadFilesystem("isofs", "iso9660", dl))) return rc;
  391.  
  392.     rc = doMount(cddev, "/tmp/rhimage", "iso9660", 1, 0);
  393.     if (rc) {
  394.         removeCDmodule(dl);
  395.         newtWinMessage(_("Error"), _("Ok"), 
  396.             _("I could not mount a CD on device /dev/%s"), cddev);
  397.         return INST_CANCEL;
  398.     }
  399.  
  400.     if (access("/tmp/rhimage/RedHat", R_OK)) {
  401.         umount("/tmp/rhimage");
  402.         removeCDmodule(dl);
  403.         newtWinMessage(_("Error"), _("Ok"), 
  404.                _("That CDROM device does "
  405.                  "not seem to contain a Red Hat CDROM."));
  406.         return INST_CANCEL;
  407.     }
  408.  
  409.     rc = 0;
  410.     while (useSupp) {
  411.         rc = floppyRoot(NULL, NULL, NULL, 0, NULL);
  412.  
  413.         logMessage("got floppy root rc=%d", rc);
  414.  
  415.         if (rc == INST_CANCEL) {
  416.         umount("/tmp/rhimage");
  417.         break;
  418.         } else if (!rc) {
  419.         logMessage("breaking out of loop");
  420.         break;
  421.         }
  422.     }
  423.  
  424.     if (!rc) break;
  425.     }
  426.  
  427.     if (!useSupp) {
  428.     if (!access("/tmp/rhimage/RedHat/instimage/lib", X_OK)) {
  429.         unlink("/tmp/rhimage/RedHat/instimage/lib");
  430.         symlink("/tmp/rhimage/RedHat/instimage/lib", "/lib");
  431.     }
  432.  
  433.     if (!access("/tmp/rhimage/RedHat/instimage/usr/bin", X_OK)) {
  434.         unlink("/tmp/rhimage/RedHat/instimage/usr/bin");
  435.         symlink("/tmp/rhimage/RedHat/instimage/usr/bin", "/usr/bin");
  436.     }
  437.  
  438.     if (!access("/tmp/rhimage/RedHat/instimage/usr/etc", X_OK)) {
  439.         unlink("/tmp/rhimage/RedHat/instimage/usr/etc");
  440.         symlink("/tmp/rhimage/RedHat/instimage/usr/etc", "/usr/etc");
  441.     }
  442.     }
  443.  
  444.     logMessage("done here");
  445.  
  446.     return 0;
  447. }
  448.  
  449. static int nfsPrepare(struct installMethod * method, struct netInfo * netc,
  450.               struct intfInfo * intf, int useSupp,
  451.               struct driversLoaded ** dl) {
  452.     char * host = NULL, * dir = NULL;
  453.     char * buf;
  454.     enum { NFS_STEP_NET, NFS_STEP_INFO, NFS_STEP_MOUNT, NFS_STEP_DONE }
  455.         step = NFS_STEP_NET;
  456.     int rc;
  457.     int ksArgc;
  458.     char ** ksArgv;
  459.     poptContext optCon;
  460.     int direction = 1;
  461.     struct poptOption ksNfsOptions[] = {
  462.         { "server", '\0', POPT_ARG_STRING, &host, 0 },
  463.         { "dir", '\0', POPT_ARG_STRING, &dir, 0 },
  464.         { 0, 0, 0, 0, 0 }
  465.     };
  466.  
  467.  
  468.     if (kickstart) {
  469.     /* FIXME: there must be a better test to use here */
  470.     if (!intf->set || !netc->set) 
  471.         if (bringUpNetworking(intf, netc, dl, 1)) return INST_ERROR;
  472.  
  473.     ksGetCommand(KS_CMD_NFS, NULL, &ksArgc, &ksArgv);
  474.  
  475.     optCon = poptGetContext(NULL, ksArgc, ksArgv, ksNfsOptions, 0);
  476.  
  477.     if ((rc = poptGetNextOpt(optCon)) < -1) {
  478.         newtWinMessage(_("nfs command"),  _("Ok"),
  479.                _("bad argument to kickstart nfs command %s: %s"),
  480.                poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
  481.                poptStrerror(rc));
  482.     }
  483.  
  484.     if (!host || !dir) {
  485.         newtWinMessage(_("nfs command"),  _("Ok"),
  486.                _("nfs command incomplete"));
  487.     } else {
  488.         step = NFS_STEP_MOUNT;
  489.     }
  490.     }
  491.  
  492.     while (step != NFS_STEP_DONE) {
  493.     switch (step) {
  494.       case NFS_STEP_NET:
  495.         rc = bringUpNetworking(intf, netc, dl, direction);
  496.         if (rc) return rc;
  497.         direction = 1;
  498.         step = NFS_STEP_INFO;
  499.         break;
  500.  
  501.       case NFS_STEP_INFO:
  502.         if (!host && (intf->set & INTFINFO_HAS_BOOTSERVER))
  503.         host = mygethostbyaddr(inet_ntoa(intf->bootServer));
  504.         if (!dir && (intf->set & INTFINFO_HAS_BOOTFILE))
  505.         dir = strdup(intf->bootFile);
  506.  
  507.         rc = nfsGetSetup(&host, &dir);
  508.         if (rc == INST_CANCEL) {
  509.         step = NFS_STEP_NET;
  510.         direction = -1;
  511.         } else if (rc == INST_ERROR)
  512.         return INST_ERROR;
  513.         else
  514.         step = NFS_STEP_MOUNT;
  515.         break;
  516.  
  517.       case NFS_STEP_MOUNT:
  518.         if (!strlen(host) || !strlen(dir))
  519.         rc = INST_ERROR;
  520.         else {
  521.         buf = malloc(strlen(host) + strlen(dir) + 10);
  522.         strcpy(buf, host);
  523.         strcat(buf, ":");
  524.         strcat(buf, dir);
  525.  
  526.         if ((rc = loadFilesystem("nfs", "nfs", dl))) return rc;
  527.  
  528.         rc = doMount(buf, "/tmp/rhimage", "nfs", 1, 0);
  529.         free(buf);
  530.         }
  531.  
  532.         if (rc) {
  533.         step = NFS_STEP_INFO;
  534.         newtWinMessage(_("Error"), _("Ok"), 
  535.                 _("I could not mount that directory from the server"));
  536.         } else {
  537.             if (access("/tmp/rhimage/RedHat", R_OK)) {
  538.             step = NFS_STEP_INFO;
  539.             newtWinMessage(_("Error"), _("Ok"), 
  540.                    _("That directory does not seem to contain "
  541.                      "a Red Hat installation tree."));
  542.             umount("/tmp/rhimage");
  543.         } else
  544.             step = NFS_STEP_DONE;
  545.         }
  546.  
  547.         rc = 0;
  548.         while (useSupp) {
  549.         rc = floppyRoot(NULL, NULL, NULL, 0, NULL);
  550.  
  551.         if (rc == INST_CANCEL) {
  552.             umount("/tmp/rhimage");
  553.             break;
  554.         } else if (!rc) {
  555.             break;
  556.         }
  557.         }
  558.  
  559.         if (rc) {
  560.         umount("/tmp/rhimage");
  561.         step = NFS_STEP_INFO;
  562.         }
  563.  
  564.         break;
  565.  
  566.       case NFS_STEP_DONE:
  567.         break;
  568.     }
  569.     }
  570.  
  571.     if (!kickstart) {
  572.     free(host);
  573.     free(dir);
  574.     }
  575.  
  576.     if (!useSupp) {
  577.     if (!access("/tmp/rhimage/RedHat/instimage/lib", X_OK)) {
  578.         unlink("/tmp/rhimage/RedHat/instimage/lib");
  579.         symlink("/tmp/rhimage/RedHat/instimage/lib", "/lib");
  580.     }
  581.  
  582.     if (!access("/tmp/rhimage/RedHat/instimage/usr/bin", X_OK)) {
  583.         unlink("/tmp/rhimage/RedHat/instimage/usr/bin");
  584.         symlink("/tmp/rhimage/RedHat/instimage/usr/bin", "/usr/bin");
  585.     }
  586.  
  587.     if (!access("/tmp/rhimage/RedHat/instimage/usr/etc", X_OK)) {
  588.         unlink("/tmp/rhimage/RedHat/instimage/usr/etc");
  589.         symlink("/tmp/rhimage/RedHat/instimage/usr/etc", "/usr/etc");
  590.     }
  591.     }
  592.  
  593.     return 0;
  594. }
  595.  
  596. int floppyRoot(struct installMethod * method, struct netInfo * netc,
  597.            struct intfInfo * intf, int forceSuppDisk,
  598.            struct driversLoaded ** dl) { 
  599.     int rc;
  600.  
  601.     if (!access("/usr/bin/runinstall2", R_OK)) {
  602.     isMounted = 1;
  603.     return 0;
  604.     }
  605.  
  606.     do {
  607.     rc = newtWinChoice(_("Supplemental Disk"), _("Ok"), _("Back"),
  608.         _("This install method requires a second disk. Please remove "
  609.           "the boot disk currently in your drive and replace it with "
  610.           "the Red Hat Supplementary Install disk."));
  611.     if (rc == 2) return INST_CANCEL;
  612.  
  613.     rc = loadFloppyRoot(method);
  614.     } while (rc);
  615.  
  616.     return 0;
  617. }
  618.  
  619. int loadFloppyRoot(struct installMethod * method) { 
  620.     int rc;
  621.  
  622.     if (isMounted) return 0;
  623.  
  624.     if (testing) return 0;
  625.  
  626.     while (doMount("fd0", "/tmp/image", "ext2", 1, 0) ||
  627.        access("/tmp/image/usr/bin/runinstall2", R_OK)) {
  628.     /* in case the mount succeeded */
  629.     umount("/tmp/image");
  630.  
  631.     rc = newtWinChoice(_("Supplemental Disk"), _("Ok"), _("Cancel"),
  632.         _("I failed to mount the floppy. Please insert the "
  633.           "Red Hat Supplementary Install disk, or choose "
  634.           "Cancel to pick a different installation process."));
  635.     if (rc == 2) return INST_CANCEL;
  636.     }
  637.  
  638.     if (totalMemory() > 8000) {
  639.     umount("/tmp/image");
  640.     loadRamdisk("ram2", "fd0", 1440, _("Loading supplemental disk..."));
  641.     if (doMount("ram2", "/tmp/image", "ext2", 1, 0)) {
  642.         errorWindow("Error mounting ramdisk. This shouldn't "
  643.                 "happen, and I'm rebooting your system now.");
  644.         exit(1);
  645.     }
  646.     } 
  647.  
  648.     symlink("/tmp/image/lib", "/lib");
  649.     symlink("/tmp/image/etc", "/etc");
  650.     symlink("/tmp/image/usr/bin", "/usr/bin");
  651.     symlink("/tmp/image/usr/etc", "/usr/etc");
  652.  
  653.     isMounted = 1;
  654.  
  655.     return 0;
  656. }
  657.  
  658.