home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / latemethods.c < prev    next >
C/C++ Source or Header  |  1997-10-14  |  29KB  |  1,113 lines

  1. #include <alloca.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <newt.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/mount.h>
  9. #include <sys/mtio.h>
  10. #include <unistd.h>
  11.  
  12. #include "hd.h"
  13. #include "fs.h"
  14. #include "ftp.h"
  15. #include "install.h"
  16. #include "log.h"
  17. #include "methods.h"
  18. #include "net.h"
  19. #include "scsi.h"
  20. #include "windows.h"
  21.  
  22. struct ftpinfo {
  23.     char * address;
  24.     char * login;
  25.     char * password;
  26.     char * prefix;
  27.     char * proxy;
  28.     int sock;
  29.     struct pkgSet ps;
  30. };
  31.  
  32. struct hdinfo {
  33.     char * device;
  34.     char * type;
  35.     char * dir;
  36. };
  37.  
  38. struct tapeCatalogEntry {
  39.     char * filename;
  40.     int size;
  41. };
  42.  
  43. struct tapeinfo {
  44.     int fd;
  45.     int offset;
  46.     int curr;
  47.     int catalogEntries;
  48.     struct tapeCatalogEntry * catalog;
  49. };
  50.  
  51. /* This was split into two pieces to keep the initial install program small */
  52.  
  53. static int ftpinstStartTransfer(struct ftpinfo * fi, char * filename);
  54. static int ftpinstFinishTransfer(struct ftpinfo * fi);
  55. static int ftpinstGetMappedFile(struct installMethod * method, char * name, 
  56.                         char ** realName, int isPreskel);
  57. static int imageGetFile(struct installMethod * method, char * name, 
  58.             char ** realName, int isPreskel);
  59. static int singleimageSetSymlinks(struct installMethod * method, 
  60.                             struct partitionTable table,
  61.                             struct netConfig * netc, 
  62.                   struct netInterface * intf,
  63.                   struct driversLoaded ** dl);
  64. static int hdSetup(struct installMethod * method, struct partitionTable table,
  65.                struct netConfig * netc, struct netInterface * intf,
  66.                struct driversLoaded ** dl);
  67. static int hdPrepareMedia(struct installMethod * method,
  68.                 struct fstab * fstab);
  69. static int hdGetPackageSet(struct installMethod * method,
  70.                  struct pkgSet * ps);
  71. static int hdGetComponentSet(struct installMethod * method,
  72.                    struct pkgSet * ps,
  73.                    struct componentSet * cs);
  74. static int ftpSetup(struct installMethod * method, struct partitionTable table,
  75.                 struct netConfig * netc, struct netInterface * intf,
  76.                 struct driversLoaded ** dl);
  77. static int ftpGetPackageSet(struct installMethod * method,
  78.                  struct pkgSet * ps);
  79. static int ftpGetComponentSet(struct installMethod * method,
  80.                    struct pkgSet * ps,
  81.                    struct componentSet * cs);
  82. static int imageGetPackageSet(struct installMethod * method,
  83.                   struct pkgSet * ps);
  84. static int imageGetComponentSet(struct installMethod * method,
  85.                  struct pkgSet * ps,
  86.                  struct componentSet * cs);
  87. static int tapeSetup(struct installMethod * method, struct partitionTable table,
  88.                  struct netConfig * netc, struct netInterface * intf,
  89.                  struct driversLoaded ** dl);
  90. static int tapeGetPackageSet(struct installMethod * method,
  91.                  struct pkgSet * ps);
  92. static int tapeGetComponentSet(struct installMethod * method,
  93.                  struct pkgSet * ps,
  94.                  struct componentSet * cs);
  95. static int tapeGetMappedFile(struct installMethod * method, char * name, 
  96.                         char ** realName, int isPreskel);
  97.  
  98. #ifdef __i386__
  99. static int smbSetup(struct installMethod * method, struct partitionTable table,
  100.                struct netConfig * netc, struct netInterface * intf,
  101.                struct driversLoaded ** dl);
  102. static int smbGetSetup(char ** hostptr, char ** dirptr, char ** acctptr,
  103.             char ** pwptr);
  104. static int smbGetPackageSet(struct installMethod * method,
  105.                  struct pkgSet * ps);
  106. static int smbGetComponentSet(struct installMethod * method,
  107.                    struct pkgSet * ps,
  108.                    struct componentSet * cs);
  109. #endif
  110.  
  111. static struct installMethod methods[] = {
  112.     { "Local CDROM",         "cdrom", 0, NULL, singleimageSetSymlinks, 
  113.         imageGetFile, 
  114.         imageGetPackageSet, imageGetComponentSet, NULL, NULL },
  115.     { "NFS image",         "nfs", 0, NULL, singleimageSetSymlinks, 
  116.         imageGetFile, 
  117.         imageGetPackageSet, imageGetComponentSet, NULL, NULL },
  118.     { "hard drive",        "hd",  0, NULL, hdSetup, imageGetFile,
  119.         hdGetPackageSet, hdGetComponentSet, hdPrepareMedia, NULL },
  120.     { "FTP",            "ftp", 1, NULL, ftpSetup, ftpinstGetMappedFile,
  121.         ftpGetPackageSet, ftpGetComponentSet, NULL, NULL },
  122. #ifdef __i386__
  123.     { "SMB image",         "smb", 0, NULL, smbSetup, 
  124.         imageGetFile, 
  125.         smbGetPackageSet, smbGetComponentSet, NULL, NULL },
  126. #endif
  127.     { "SCSI Tape",         "tape", 1, NULL, tapeSetup, tapeGetMappedFile,
  128.         tapeGetPackageSet, tapeGetComponentSet, NULL },
  129. } ;
  130. static int numMethods = sizeof(methods) / sizeof(struct installMethod);
  131.  
  132. struct installMethod * findInstallMethod(char * argptr) {
  133.     int i;
  134.  
  135.     for (i = 0; i < numMethods; i++) 
  136.     if (!strcmp(argptr, methods[i].abbrev)) return (methods + i);
  137.  
  138.     return NULL;
  139. }
  140.  
  141. static int imageGetFile(struct installMethod * method, char * name, 
  142.             char ** realName, int isPreskel) {
  143.     static char buf[300];
  144.  
  145.     if (!strcmp(name, "hdlist") || !strcmp(name, "rpmconvert"))
  146.     strcpy(buf, "/tmp/rhimage/RedHat/base/");
  147.     else
  148.     strcpy(buf, "/tmp/rhimage/RedHat/RPMS/");
  149.  
  150.     strcat(buf, name);
  151.     *realName = buf;
  152.  
  153.     return 0;
  154. }
  155.  
  156. static int hdSetup(struct installMethod * method, struct partitionTable table,
  157.                struct netConfig * netc, struct netInterface * intf,
  158.                struct driversLoaded ** dl) {
  159.     newtComponent okay, cancel, form, text, listbox, label, answer, dirEntry;
  160.     int i, j;
  161.     char buf[80];
  162.     struct partition * part = NULL;
  163.     char * type;
  164.     char * dir;
  165.     char * dest;
  166.     char * defaultDevice;
  167.     char * defaultDir;
  168.     int done = 0;
  169.     struct hdinfo * hdi;
  170.  
  171.     if (method->data) {
  172.     hdi = method->data;
  173.     defaultDir = strdup(hdi->dir);
  174.     defaultDevice = hdi->device;
  175.     } else {
  176.     defaultDir = strdup("/");
  177.     defaultDevice = "";
  178.     }
  179.  
  180.     while (!done) {
  181.     newtCenteredWindow(64, 17, "Select Partition");
  182.     text = newtTextbox(1, 1, 62, 4, NEWT_TEXTBOX_WRAP);
  183.     newtTextboxSetText(text, "What partition and directory on that "
  184.                 "partition hold the RedHat/RPMS and "
  185.                 "RedHat/base directories?");
  186.     okay = newtButton(15, 13, "Ok");
  187.     cancel = newtButton(38, 13, "Cancel");
  188.  
  189.     form = newtForm(NULL, NULL, 0);
  190.  
  191.     listbox = newtListbox(7, 5, 5, NEWT_LISTBOX_RETURNEXIT);
  192.  
  193.     label = 
  194.         newtLabel(5, 4, "  Device          Begin        End   Size (k)");
  195.  
  196.     for (i = 0, j = 0; i < table.count; i++) {
  197.         if (table.parts[i].type == PART_EXT2 ||
  198.         table.parts[i].type == PART_DOS) {
  199.         sprintf(buf, "/dev/%-5s  %9d  %9d  %9d", table.parts[i].device, 
  200.             table.parts[i].begin, table.parts[i].end, 
  201.             table.parts[i].size);
  202.         newtListboxAddEntry(listbox, buf, &table.parts[i]);
  203.     
  204.         if (!strcmp(table.parts[i].device, defaultDevice)) {
  205.             newtListboxSetCurrent(listbox, j);
  206.         }
  207.  
  208.         j++;
  209.         }
  210.     }
  211.  
  212.     newtFormAddComponent(form, 
  213.                 newtLabel(1, 11, "Directory holding Red Hat:"));
  214.     dirEntry = newtEntry(28, 11, defaultDir, 28, &dir, NEWT_ENTRY_SCROLL);
  215.  
  216.     newtFormAddComponents(form, text, label, listbox, dirEntry,
  217.                 okay, cancel, NULL);
  218.     answer = newtRunForm(form);
  219.                 
  220.     if (answer != cancel) {
  221.         part = newtListboxGetCurrent(listbox);
  222.     }
  223.  
  224.     dir = strdup(dir);
  225.     free(defaultDir);
  226.     defaultDir = dir;
  227.     defaultDevice = part->device;
  228.  
  229.     newtFormDestroy(form);
  230.     newtPopWindow();
  231.  
  232.     if (answer == cancel) return INST_CANCEL;
  233.  
  234.     switch (part->type) {
  235.       case PART_EXT2:    type = "ext2";         break;
  236.       case PART_DOS:    type = "msdos";     break;
  237.       default:    continue;
  238.     }
  239.  
  240.     if (doMount(part->device, "/tmp/hdimage", type, 1, 0))
  241.         continue;
  242.  
  243.     unlink("/tmp/rhimage");
  244.     
  245.     /* the physical device is mounted on /tmp/hdimage, but all
  246.        access are through /tmp/rhimage which points to the RedHat
  247.        directory in /tmp/hdimage */
  248.  
  249.     dest = alloca(strlen(dir) + 20);
  250.     sprintf(dest, "/tmp/hdimage/%s", dir);
  251.  
  252.     if (symlink(dest, "/tmp/rhimage")) {
  253.         newtWinMessage("Error", "Ok", "Failed to create /tmp/rhimage "
  254.                 "symlink: %s", strerror(errno));
  255.         umount("/tmp/hdimage");
  256.         continue;
  257.     } 
  258.  
  259.     if (access("/tmp/rhimage/RedHat/base/hdlist", R_OK)) {
  260.         newtWinMessage("Error", "Ok", 
  261.             "Device %s does not appear to contain "
  262.             "a Red Hat installation tree.", part->device);
  263.         umount("/tmp/hdimage");
  264.         continue;
  265.     } 
  266.  
  267.     if (method->data) {
  268.         hdi = method->data;
  269.         free(hdi->dir);
  270.     }
  271.     
  272.     hdi = malloc(sizeof(*hdi));
  273.     hdi->device = part->device;
  274.     hdi->type = type;
  275.     hdi->dir = strdup(dir);
  276.     method->data = hdi;
  277.  
  278.     done = 1; 
  279.  
  280.     umount("/tmp/hdimage");
  281.     }
  282.  
  283.     return 0;
  284. }
  285.  
  286. static int hdGetPackageSet(struct installMethod * method,
  287.                  struct pkgSet * ps) {
  288.     struct hdinfo * hdi = method->data;
  289.     int rc;
  290.  
  291.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  292.     return INST_ERROR;
  293.  
  294.     rc = psUsingDirectory("/tmp/rhimage/RedHat/RPMS", ps);
  295.     
  296.     umount("/tmp/hdimage");
  297.  
  298.     return rc;
  299. }
  300.  
  301. static int hdGetComponentSet(struct installMethod * method,
  302.                    struct pkgSet * ps,
  303.                    struct componentSet * cs) {
  304.     struct hdinfo * hdi = method->data;
  305.     int rc;
  306.  
  307.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  308.     return INST_ERROR;
  309.  
  310.     rc = psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  311.     
  312.     umount("/tmp/hdimage");
  313.  
  314.     return rc;
  315. }
  316.  
  317. static int hdPrepareMedia(struct installMethod * method,
  318.                 struct fstab * fstab) {
  319.     struct hdinfo * hdi = method->data;
  320.     int i;
  321.     char * buf;
  322.  
  323.     for (i = 0; i < fstab->numEntries; i++) {
  324.     if (fstab->entries[i].isMounted &&
  325.         !strcmp(fstab->entries[i].device, hdi->device)) break;
  326.     }
  327.  
  328.     if (i < fstab->numEntries) {
  329.     logMessage("device %s is already mounted -- using symlink",
  330.             fstab->entries[i].device);
  331.     buf = alloca(strlen(fstab->entries[i].mntpoint) + 10);
  332.  
  333.     sprintf(buf, "/mnt/%s", fstab->entries[i].mntpoint);
  334.     
  335.     rmdir("/tmp/hdimage");
  336.     if (symlink(buf, "/tmp/hdimage")) {
  337.         logMessage("failed to create symlink %s: %s\n", 
  338.             buf, strerror(errno));
  339.         newtWinMessage("Error", "Ok", 
  340.                "Failed to create symlink for package source.");
  341.         return INST_ERROR;
  342.     }
  343.     } else {
  344.     logMessage("mounting device which contains packages");
  345.     if (doMount(hdi->device, "/tmp/hdimage", hdi->type, 1, 0))
  346.         return INST_ERROR;
  347.     }
  348.  
  349.     return 0;
  350. }
  351.  
  352. static int imageGetPackageSet(struct installMethod * method,
  353.                   struct pkgSet * ps) {
  354.     return psFromHeaderListFile("/tmp/rhimage/RedHat/base/hdlist", ps);
  355. }
  356.  
  357. static int imageGetComponentSet(struct installMethod * method,
  358.                     struct pkgSet * ps,
  359.                     struct componentSet * cs) {
  360.     return psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  361. }
  362.  
  363. static int singleimageSetSymlinks(struct installMethod * method, 
  364.                             struct partitionTable table,
  365.                             struct netConfig * netc, 
  366.                   struct netInterface * intf,
  367.                   struct driversLoaded ** dl) {
  368.     logMessage("making symlink from /tmp/rhimage to image");
  369.     symlink("rhimage", "/tmp/image");
  370.     return 0;
  371. }
  372.  
  373. /* returns a socket file descriptor, a ftpFinishTransfer() must occur after 
  374.    this call */
  375. static int ftpinstStartTransfer(struct ftpinfo * fi, char * filename) {
  376.     char * buf;
  377.     newtComponent form;
  378.     int fd;
  379.  
  380.     logMessage("ftping %s to a fd", filename);
  381.  
  382.     newtCenteredWindow(60, 3, "Retrieving");
  383.  
  384.     buf = alloca(strlen(fi->prefix) + strlen(filename) + 30);
  385.     sprintf(buf, "Retrieving %s...", filename);
  386.     form = newtForm(NULL, NULL, 0);
  387.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  388.  
  389.     newtDrawForm(form);
  390.     newtRefresh();
  391.  
  392.     strcpy(buf, fi->prefix);
  393.     strcat(buf, "/RedHat/");
  394.     strcat(buf, filename);
  395.     fd = ftpGetFileDesc(fi->sock, buf);
  396.  
  397.     return fd;
  398. }
  399.  
  400. static int ftpinstFinishTransfer(struct ftpinfo * fi) {
  401.     newtPopWindow();
  402.  
  403.     return ftpGetFileDone(fi->sock);
  404. }
  405.  
  406. static int ftpinstGetFile(struct ftpinfo * fi, char * filename, char * dest) {
  407.     char * buf;
  408.     newtComponent form;
  409.     int fd, rc;
  410.  
  411.     logMessage("ftping %s as %s", filename, dest);
  412.  
  413.     newtCenteredWindow(60, 3, "Retrieving");
  414.  
  415.     buf = alloca(strlen(fi->prefix) + strlen(filename) + 30);
  416.     sprintf(buf, "Retrieving %s...", filename);
  417.     form = newtForm(NULL, NULL, 0);
  418.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  419.  
  420.     newtDrawForm(form);
  421.     newtRefresh();
  422.  
  423.     fd = open(dest, O_WRONLY | O_CREAT, 0644);
  424.     if (fd < 0) {
  425.     newtWinMessage("Error", "Ok", "open of %s failed: %s\n", dest, 
  426.             strerror(errno));
  427.     return INST_ERROR;
  428.     }
  429.  
  430.     strcpy(buf, fi->prefix);
  431.     strcat(buf, "/RedHat/");
  432.     strcat(buf, filename);
  433.     rc = ftpGetFile(fi->sock, buf, fd);
  434.  
  435.     close(fd);
  436.  
  437.     newtFormDestroy(form);
  438.     newtPopWindow();
  439.  
  440.     if (rc) {
  441.     newtWinMessage("ftp", "Ok", "I cannot get file %s: %s\n", buf,
  442.             ftpStrerror(rc));
  443.     return INST_ERROR;
  444.     }
  445.  
  446.     return 0;
  447. }
  448.  
  449. static int ftpMainSetupPanel(struct ftpinfo * fi, char * doSecondarySetup) {
  450.     newtComponent form, okay, cancel, siteEntry, dirEntry, answer, text, cb;
  451.     char * site, * dir;
  452.  
  453.     if (fi->address) {
  454.     site = fi->address;
  455.     dir = fi->prefix;
  456.     } else {
  457.     site = "";
  458.     dir = "";
  459.     }
  460.  
  461.     if (fi->login || fi->password || fi->login)
  462.     *doSecondarySetup = 'X';
  463.     else
  464.     *doSecondarySetup = ' ';
  465.  
  466.     newtCenteredWindow(50, 17, "FTP Setup");
  467.  
  468.     form = newtForm(NULL, NULL, 0);
  469.     okay = newtButton(10, 13, "Ok");
  470.     cancel = newtButton(30, 13, "Cancel");
  471.  
  472.     text = newtTextbox(1, 1, 47, 8, NEWT_TEXTBOX_WRAP);
  473.     newtTextboxSetText(text,
  474.     "Please enter the following information:\n"
  475.     "\n"
  476.     "    o the name or IP number of your FTP server\n"
  477.     "    o the directory on that server containing\n"
  478.     "      Red Hat Linux for your architecure\n");
  479.  
  480.     newtFormAddComponent(form, newtLabel(3, 8, "FTP site name    :"));
  481.     newtFormAddComponent(form, newtLabel(3, 9, "Red Hat directory:"));
  482.  
  483.     siteEntry = newtEntry(22, 8, site, 24, &site, NEWT_ENTRY_SCROLL);
  484.     dirEntry = newtEntry(22, 9, dir, 24, &dir, NEWT_ENTRY_SCROLL);
  485.  
  486.     cb = newtCheckbox(3, 11, "Use non-anonymous ftp or a proxy server",
  487.             *doSecondarySetup, NULL, doSecondarySetup);
  488.  
  489.     newtFormAddComponents(form, text, siteEntry, dirEntry, cb, okay, cancel, 
  490.               NULL);
  491.  
  492.     answer = newtRunForm(form);
  493.     if (answer == cancel) {
  494.     newtFormDestroy(form);
  495.     newtPopWindow();
  496.     
  497.     return INST_CANCEL;
  498.     }
  499.  
  500.     if (fi->address) free(fi->address);
  501.     fi->address = strdup(site);
  502.  
  503.     if (fi->prefix) free(fi->prefix);
  504.     fi->prefix = strdup(dir);
  505.  
  506.     newtFormDestroy(form);
  507.     newtPopWindow();
  508.  
  509.     return 0;
  510. }
  511.  
  512. static int ftpSecondarySetupPanel(struct ftpinfo * fi) {
  513.     newtComponent form, okay, cancel, answer, text, accountEntry;
  514.     newtComponent passwordEntry, proxyEntry;
  515.     char * account, * password, * proxy;
  516.  
  517.     newtCenteredWindow(50, 15, "Further FTP Setup");
  518.  
  519.     form = newtForm(NULL, NULL, 0);
  520.     okay = newtButton(10, 11, "Ok");
  521.     cancel = newtButton(30, 11, "Cancel");
  522.  
  523.     text = newtTextbox(1, 1, 47, 8, NEWT_TEXTBOX_WRAP);
  524.     newtTextboxSetText(text,
  525.     "If you are using non anonymous ftp, enter the account "
  526.     "name and password you wish to use below. If you are "
  527.     "using an FTP proxy enter the name of the FTP proxy server "
  528.     "to use.");
  529.  
  530.     newtFormAddComponent(form, newtLabel(3, 6, "Account name :"));
  531.     newtFormAddComponent(form, newtLabel(3, 7, "Password     :"));
  532.  
  533.     newtFormAddComponent(form, newtLabel(3, 9, "FTP Proxy    :"));
  534.  
  535.     accountEntry = newtEntry(18, 6, fi->login, 24, &account, NEWT_ENTRY_SCROLL);
  536.     passwordEntry = newtEntry(18, 7, NULL, 24, &password, 
  537.                 NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN);
  538.     proxyEntry = newtEntry(18, 9, fi->proxy, 24, &proxy, NEWT_ENTRY_SCROLL);
  539.  
  540.     newtFormAddComponents(form, text, accountEntry, passwordEntry, proxyEntry, 
  541.               okay, cancel, NULL);
  542.  
  543.     answer = newtRunForm(form);
  544.     if (answer == cancel) {
  545.     newtFormDestroy(form);
  546.     newtPopWindow();
  547.     
  548.     return INST_CANCEL;
  549.     }
  550.  
  551.     if (fi->login) free(fi->login);
  552.     if (strlen(account))
  553.     fi->login = strdup(account);
  554.     else
  555.     fi->login = NULL;
  556.  
  557.     if (fi->password) free(fi->password);
  558.     if (strlen(password))
  559.     fi->password = strdup(password);
  560.     else
  561.     fi->password = NULL;
  562.  
  563.     if (fi->proxy) free(fi->proxy);
  564.     if (strlen(proxy))
  565.     fi->proxy = strdup(proxy);
  566.     else
  567.     fi->proxy = NULL;
  568.  
  569.     newtFormDestroy(form);
  570.     newtPopWindow();
  571.  
  572.     return 0;
  573. }
  574.  
  575. static int ftpSetup(struct installMethod * method, struct partitionTable table,
  576.                 struct netConfig * netc, struct netInterface * intf,
  577.                 struct driversLoaded ** dl) {
  578.     struct ftpinfo fi;
  579.     enum { FTP_SETUP_NET, FTP_SETUP_FTP1, FTP_SETUP_FTP2, FTP_SETUP_CHECK, 
  580.         FTP_SETUP_DONE } step = FTP_SETUP_NET;
  581.     int rc, fd;
  582.     char doMore;
  583.  
  584.     memset(&fi, 0, sizeof(fi));
  585.  
  586.     if (method->data)
  587.     memcpy(&fi, method->data, sizeof(fi));
  588.     else
  589.     memset(&fi, 0, sizeof(fi));
  590.  
  591.     while (step != FTP_SETUP_DONE) {
  592.     switch (step) {
  593.  
  594.       case FTP_SETUP_NET:
  595.         rc = bringUpNetworking(intf, netc, dl);
  596.         if (rc) return rc;
  597.         step = FTP_SETUP_FTP1;
  598.         break;
  599.  
  600.       case FTP_SETUP_FTP1:
  601.         rc = ftpMainSetupPanel(&fi, &doMore);
  602.         if (rc == INST_ERROR) 
  603.         return rc;
  604.         else if (rc)
  605.         step = FTP_SETUP_NET;
  606.         else if (doMore == ' ')
  607.         step = FTP_SETUP_CHECK;
  608.         else 
  609.         step = FTP_SETUP_FTP2;
  610.         break;
  611.  
  612.       case FTP_SETUP_FTP2:
  613.         rc = ftpSecondarySetupPanel(&fi);
  614.         if (rc == INST_ERROR) 
  615.         return rc;
  616.         else if (rc)
  617.         step = FTP_SETUP_FTP1;
  618.         else
  619.         step = FTP_SETUP_CHECK;
  620.         break;
  621.  
  622.       case FTP_SETUP_CHECK:
  623.         if ((fi.sock = ftpOpen(fi.address, fi.login, 
  624.                    fi.password ? fi.password : "rhinstall@", 
  625.                    fi.proxy, -1)) < 0) {
  626.         newtWinMessage("ftp", "Ok", "I cannot log into machine: %s\n",
  627.                 ftpStrerror(fi.sock));
  628.         step = FTP_SETUP_FTP1;
  629.         break;
  630.         }
  631.  
  632.         
  633.         fd = ftpinstStartTransfer(&fi, "base/hdlist");
  634.         if (fd < 0) {
  635.         newtPopWindow();
  636.         ftpClose(fi.sock);
  637.         step = FTP_SETUP_FTP1;
  638.         break;
  639.         }
  640.  
  641.         if (psFromHeaderListDesc(fd, &fi.ps, 1)) {
  642.         ftpClose(fi.sock);
  643.         step = FTP_SETUP_FTP1;
  644.         break;
  645.         }
  646.  
  647.         ftpinstFinishTransfer(&fi);
  648.  
  649.         if (ftpinstGetFile(&fi, "base/comps", "/tmp/comps")) {
  650.         ftpClose(fi.sock);
  651.         step = FTP_SETUP_FTP1;
  652.         break;
  653.         }
  654.         
  655.         step = FTP_SETUP_DONE;
  656.         break;
  657.  
  658.       case FTP_SETUP_DONE:
  659.         break;
  660.     }
  661.     }
  662.  
  663.     if (method->data) free(method->data);
  664.     method->data = malloc(sizeof(fi));
  665.     memcpy(method->data, &fi, sizeof(fi));
  666.  
  667.     return 0;
  668. }
  669.  
  670. static int ftpGetPackageSet(struct installMethod * method,
  671.                  struct pkgSet * ps) {
  672.     struct ftpinfo * fi = method->data;
  673.  
  674.     *ps = fi->ps;
  675.     return 0;
  676. }
  677.  
  678. static int ftpGetComponentSet(struct installMethod * method,
  679.                    struct pkgSet * ps,
  680.                    struct componentSet * cs) {
  681.     return psReadComponentsFile("/tmp/comps", ps, cs);
  682. }
  683.  
  684. static int ftpinstGetMappedFile(struct installMethod * method, char * name, 
  685.                         char ** realName, int isPreskel) {
  686.     static char sbuf[300];
  687.     char * buf;
  688.     int rc;
  689.     struct ftpinfo * fi = method->data;
  690.  
  691.     if (isPreskel)
  692.     strcpy(sbuf, "/mnt/");
  693.     else
  694.     strcpy(sbuf, "/mnt/var/tmp/");
  695.  
  696.     strcat(sbuf, name);
  697.     *realName = sbuf;
  698.  
  699.     buf = alloca(strlen(name) + 30);
  700.     if (!strcmp(name, "hdlist") || !strcmp(name, "rpmconvert"))
  701.     strcpy(buf, "base/");
  702.     else
  703.     strcpy(buf, "RPMS/");
  704.     strcat(buf, name);
  705.  
  706.     rc = ftpinstGetFile(fi, buf, *realName);
  707.     if (!rc) return 0;
  708.  
  709.     /* Try again, and relogin */
  710.     ftpClose(fi->sock);
  711.  
  712.     if ((fi->sock = ftpOpen(fi->address, fi->login, 
  713.                 fi->password ? fi->password : "rhinstall@", 
  714.                 fi->proxy, -1)) 
  715.         < 0) {
  716.     newtWinMessage("ftp", "Ok", "I cannot log into machine: %s\n",
  717.             ftpStrerror(fi->sock));
  718.     free(fi);
  719.     return INST_ERROR;
  720.     }
  721.  
  722.     return ftpinstGetFile(fi, buf, *realName);
  723. }
  724.  
  725. int tapeOp(int fd, int cmd, int count, int reportErr) {
  726.     struct mtop mtcmd;
  727.  
  728.     mtcmd.mt_op = cmd;
  729.     mtcmd.mt_count = count;
  730.  
  731.     if (ioctl(fd, MTIOCTOP, &mtcmd)) {
  732.     if (reportErr)
  733.         newtWinMessage("Tape Error", "Ok", "tape ioctl %d failed: %s",
  734.               cmd, strerror(errno));
  735.     return 1;
  736.     }
  737.  
  738.     return 0;
  739. }
  740.  
  741. static int tapeSetup(struct installMethod * method, struct partitionTable table,
  742.                  struct netConfig * netc, struct netInterface * intf,
  743.                  struct driversLoaded ** dl) {
  744.     int rc;
  745.     int fd;
  746.     int catalogAlloced;
  747.     struct tapeinfo * info;
  748.     char magic[5];
  749.     int foundit = 0;
  750.     char catalogBuf[16384];
  751.     char * chptr, * start, * next;
  752.     int offset = 0;
  753.  
  754.     /* eventually we should support devices other then /dev/nst0 */
  755.     if ((rc = setupSCSIInterfaces(1, dl))) return rc;
  756.  
  757.     if ((rc = devMakeInode("nst0", "/tmp/nst0"))) return rc;
  758.  
  759.     if ((fd = open("/tmp/nst0", O_RDONLY)) < 0) {
  760.     devRemoveInode("/tmp/nst0");
  761.  
  762.     if (errno == ENODEV) {
  763.         newtWinMessage("Error", "Ok", "I couldn't find any SCSI tape drives.");
  764.     } else {
  765.         errorWindow("Error opening device nst0: %s");
  766.     }
  767.  
  768.     return INST_ERROR;
  769.     }
  770.  
  771.     winStatus(45, 3, "Tape", "Looking for Red Hat tape image...");
  772.  
  773.     /* now, let's see if we can find the file on the tape */
  774.     if ((rc = read(fd, magic, sizeof(magic))) == sizeof(magic)) {
  775.     if (!strcmp(magic, "1234\n")) {
  776.         logMessage("found magic on first try");
  777.         foundit = 1;
  778.     }
  779.     } else if (rc < 0) {
  780.     newtWinMessage("Error", "Ok", "Error reading from tape: %s", strerror(errno));
  781.     }
  782.  
  783.     if (!foundit) {
  784.     logMessage("seeking to next file");
  785.     if (tapeOp(fd, MTFSF, 1, 0)) {
  786.         logMessage("failed to find beginning of next file: %s",
  787.             strerror(errno));
  788.     } else {
  789.         if ((rc = read(fd, magic, sizeof(magic))) == sizeof(magic)) {
  790.         if (!strcmp(magic, "1234\n")) {
  791.             logMessage("found magic on second try");
  792.             foundit = 1;
  793.             offset = 1;
  794.         }
  795.         }
  796.     }
  797.     }
  798.  
  799.     if (!foundit) {
  800.     errorWindow("I can't find the Red Hat tape installation image"
  801.             "on that tape.");
  802.     close(fd);
  803.     newtPopWindow();
  804.  
  805.     return INST_ERROR;
  806.     } 
  807.  
  808.     if ((rc = read(fd, catalogBuf, sizeof(catalogBuf) - 1)) < 0) {
  809.     errorWindow("Error reading file catalog from tape: %s");
  810.     newtPopWindow();
  811.     close(fd);
  812.     return INST_ERROR;
  813.     }
  814.  
  815.     newtPopWindow();
  816.  
  817.     info = malloc(sizeof(*info));
  818.     info->fd = fd;
  819.     info->offset = offset;
  820.     info->curr = -1;
  821.     method->data = info;
  822.         
  823.     /* read in the catalog */
  824.     catalogAlloced = 20;
  825.     info->catalog = malloc(sizeof(*info->catalog) * catalogAlloced);
  826.     info->catalogEntries = 0;
  827.  
  828.     start = catalogBuf;
  829.     while (strncmp(start, "--done--", 8)) {
  830.     chptr = strchr(start, '\n');
  831.     next = chptr + 1;
  832.     *chptr = '\0';
  833.     while (*chptr != ' ') chptr--;
  834.     *chptr = '\0';
  835.     chptr++;
  836.  
  837.     if (info->catalogEntries == catalogAlloced) {
  838.         catalogAlloced += 20;
  839.             info->catalog = realloc(info->catalog, 
  840.                     sizeof(*info->catalog) * catalogAlloced);
  841.     }
  842.     
  843.     info->catalog[info->catalogEntries].filename = strdup(start);
  844.     info->catalog[info->catalogEntries].size = strtoul(chptr, NULL, 10);
  845.     info->catalogEntries++;
  846.     
  847.     start = next;
  848.     }
  849.     
  850.     return 0;
  851. }
  852.  
  853. static int tapeGetPackageSet(struct installMethod * method,
  854.                  struct pkgSet * ps) {
  855.     struct tapeinfo * info = method->data;
  856.  
  857.     if (tapeOp(info->fd, MTFSF, 1, 1)) return INST_ERROR;
  858.     info->curr++;
  859.     return psFromHeaderListDesc(info->fd, ps, 1);
  860. }
  861.  
  862. static int tapeCopyFile(struct tapeinfo * info, char * tapename, char * out) {
  863.     int outfd;
  864.     char buf[4096];
  865.     int i;
  866.     int total, amount;
  867.     int done = 0;
  868.  
  869.     /* let's figure out where we need to go */
  870.     for (i = 0; i < info->catalogEntries; i++) {
  871.     if (!strcmp(tapename, info->catalog[i].filename)) break;
  872.     }
  873.  
  874.     if (i < 0) {
  875.     newtWinMessage("Error", "Ok", "I can't find file %s on the tape", tapename);
  876.     return INST_ERROR;    
  877.     }
  878.  
  879.     if (i < info->curr) {
  880.     newtWinMessage("Error", "Ok", "The tape is not positioned properly");
  881.     return INST_ERROR;    
  882.     } else {
  883.     logMessage("skipping %d files on the tape to get to %s", 
  884.             i - info->curr, tapename);
  885.     while (i > info->curr) {
  886.         if (tapeOp(info->fd, MTFSF, 1, 1)) return INST_ERROR;
  887.         logMessage("skipped file");
  888.         info->curr++;
  889.     }
  890.     }
  891.  
  892.     if ((outfd = open(out, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) {
  893.     newtWinMessage("Error", "Ok", "failed to create %s: %s", out, 
  894.             strerror(errno));
  895.     return INST_ERROR;
  896.     }
  897.  
  898.     total = 0;
  899.     while (!done) {
  900.     amount = read(info->fd, buf, sizeof(buf));
  901.  
  902.     if (amount < 0)
  903.         break;
  904.     
  905.     if (((total + amount) > info->catalog[i].size)) {
  906.         done = 1;
  907.         amount = info->catalog[i].size - total;
  908.     }
  909.     if (write(outfd, buf, amount) != amount) {
  910.         newtWinMessage("Error", "Ok", "failed to write to %s: %s", out, 
  911.                 strerror(errno));
  912.         close(outfd);
  913.         return INST_ERROR;
  914.     }
  915.  
  916.     total += amount;
  917.     }
  918.  
  919.     if (i < 0) {
  920.     newtWinMessage("Error", "Ok", "failed to read from tape: %s", out, 
  921.             strerror(errno));
  922.     close(outfd);
  923.     return INST_ERROR;
  924.     }
  925.  
  926.     close(outfd);
  927.  
  928.     return 0;
  929. }
  930.  
  931. static int tapeGetComponentSet(struct installMethod * method,
  932.                  struct pkgSet * ps,
  933.                  struct componentSet * cs) {
  934.     struct tapeinfo * info = method->data;
  935.     int rc;
  936.     
  937.     if ((rc = tapeCopyFile(info, "comps", "/tmp/comps"))) return rc;
  938.  
  939.     return psReadComponentsFile("/tmp/comps", ps, cs);
  940. }
  941.  
  942. static int tapeGetMappedFile(struct installMethod * method, char * name, 
  943.                         char ** realName, int isPreskel) {
  944.     static char sbuf[300];
  945.     int rc;
  946.     struct tapeinfo * info = method->data;
  947.  
  948.     if (isPreskel)
  949.     strcpy(sbuf, "/mnt/");
  950.     else
  951.     strcpy(sbuf, "/mnt/var/tmp/");
  952.  
  953.     strcat(sbuf, name);
  954.     *realName = sbuf;
  955.  
  956.     return (rc = tapeCopyFile(info, name, sbuf));
  957. }
  958.  
  959. #ifdef __i386__
  960. static int smbSetup(struct installMethod * method, struct partitionTable table,
  961.                struct netConfig * netc, struct netInterface * intf,
  962.                struct driversLoaded ** dl) {
  963.     char * host = NULL, * dir = NULL, * acct = NULL, * pass = NULL;
  964.     char * buf;
  965.     static int moduleLoaded = 0;
  966.     enum { SMB_STEP_NET, SMB_STEP_INFO, SMB_STEP_MOUNT, SMB_STEP_DONE }
  967.         step = SMB_STEP_NET;
  968.     int rc;
  969.  
  970.     while (step != SMB_STEP_DONE) {
  971.     switch (step) {
  972.       case SMB_STEP_NET:
  973.         rc = bringUpNetworking(intf, netc, dl);
  974.         if (rc) return rc;
  975.         step = SMB_STEP_INFO;
  976.         break;
  977.  
  978.       case SMB_STEP_INFO:
  979.         rc = smbGetSetup(&host, &dir, &acct, &pass);
  980.         if (rc == INST_CANCEL)
  981.         step = SMB_STEP_NET;
  982.         else if (rc == INST_ERROR)
  983.         return INST_ERROR;
  984.         else
  985.         step = SMB_STEP_MOUNT;
  986.         break;
  987.  
  988.       case SMB_STEP_MOUNT:
  989.         if (!strlen(host) || !strlen(dir))
  990.         rc = INST_ERROR;
  991.         else {
  992.         buf = malloc(strlen(host) + strlen(dir) + 10);
  993.         strcpy(buf, host);
  994.         strcat(buf, ":");
  995.         strcat(buf, dir);
  996.  
  997.         if (!moduleLoaded) {
  998.             rc = loadModule("smbfs", DRIVER_FS, DRIVER_MINOR_NONE, dl);
  999.             if (rc) return rc;
  1000.             moduleLoaded = 1;
  1001.         }
  1002.  
  1003.         rc = doPwMount(buf, "/tmp/rhimage", "smb", 1, 0, acct, pass);
  1004.  
  1005.         free(buf);
  1006.         }
  1007.  
  1008.         if (rc) {
  1009.         step = SMB_STEP_INFO;
  1010.         newtWinMessage("Error", "Ok", 
  1011.             "I could not mount that directory from the server");
  1012.         } else {
  1013.             if (access("/tmp/rhimage/RedHat", R_OK)) {
  1014.             step = SMB_STEP_INFO;
  1015.             newtWinMessage("Error", "Ok", "That directory does not seem "
  1016.                   "to contain a Red Hat installation tree.");
  1017.             umount("/tmp/rhimage");
  1018.         } else
  1019.             step = SMB_STEP_DONE;
  1020.         }
  1021.  
  1022.         break;
  1023.  
  1024.       case SMB_STEP_DONE:
  1025.         break;
  1026.     }
  1027.     }
  1028.  
  1029.     free(host);
  1030.     free(dir);
  1031.  
  1032.     return 0;
  1033. }
  1034.  
  1035. static int smbGetSetup(char ** hostptr, char ** dirptr, char ** acctptr,
  1036.             char ** pwptr) {
  1037.     newtComponent form, okay, cancel, siteEntry, dirEntry, answer, text;
  1038.     newtComponent acctEntry, passEntry;
  1039.     char * site, * dir, * acct, * pass;
  1040.  
  1041.     if (*hostptr) {
  1042.     site = *hostptr;
  1043.     dir = *dirptr;
  1044.     acct = *acctptr;
  1045.     pass = *pwptr;
  1046.     } else {
  1047.     site = "";
  1048.     dir = "";
  1049.     acct = "";
  1050.     pass = "";
  1051.     }
  1052.  
  1053.     newtCenteredWindow(50, 16, "SMB Setup");
  1054.  
  1055.     form = newtForm(NULL, NULL, 0);
  1056.     okay = newtButton(10, 12, "Ok");
  1057.     cancel = newtButton(30, 12, "Cancel");
  1058.  
  1059.     text = newtTextbox(1, 1, 47, 5, NEWT_TEXTBOX_WRAP);
  1060.     newtTextboxSetText(text,
  1061.     "Please enter the following information:\n"
  1062.     "\n"
  1063.     "    o the name or IP number of your SMB server\n"
  1064.     "    o the volume to share which contains\n"
  1065.     "      Red Hat Linux for your architecture");
  1066.  
  1067.     newtFormAddComponent(form, newtLabel(3, 7,  "SMB server name  :"));
  1068.     newtFormAddComponent(form, newtLabel(3, 8,  "Share volume     :"));
  1069.     newtFormAddComponent(form, newtLabel(3, 9,  "Account name     :"));
  1070.     newtFormAddComponent(form, newtLabel(3, 10, "Password         :"));
  1071.  
  1072.     siteEntry = newtEntry(22, 7, site, 24, &site, NEWT_ENTRY_SCROLL);
  1073.     dirEntry = newtEntry(22, 8, dir, 24, &dir, NEWT_ENTRY_SCROLL);
  1074.     acctEntry = newtEntry(22, 9, "guest", 24, &acct, NEWT_ENTRY_SCROLL);
  1075.     passEntry = newtEntry(22, 10, pass, 24, &pass, 
  1076.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN);
  1077.  
  1078.     newtFormAddComponents(form, text, siteEntry, dirEntry, acctEntry,
  1079.               passEntry, okay, cancel, NULL);
  1080.  
  1081.     answer = newtRunForm(form);
  1082.     if (answer == cancel) {
  1083.     newtFormDestroy(form);
  1084.     newtPopWindow();
  1085.     
  1086.     return INST_CANCEL;
  1087.     }
  1088.  
  1089.     *hostptr = strdup(site);
  1090.     *dirptr = strdup(dir);
  1091.     *acctptr = strdup(acct);
  1092.     *pwptr = strdup(pass);
  1093.  
  1094.     newtFormDestroy(form);
  1095.     newtPopWindow();
  1096.  
  1097.     return 0;
  1098. }
  1099.  
  1100. static int smbGetPackageSet(struct installMethod * method,
  1101.                  struct pkgSet * ps) {
  1102.     return psUsingDirectory("/tmp/rhimage/RedHat/RPMS", ps);
  1103. }
  1104.  
  1105. static int smbGetComponentSet(struct installMethod * method,
  1106.                    struct pkgSet * ps,
  1107.                    struct componentSet * cs) {
  1108.     return psReadComponentsFile("/tmp/rhimage/RedHat/base/comps", ps, cs);
  1109. }
  1110.  
  1111.  
  1112. #endif
  1113.