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

  1. #include <alloca.h>
  2. #include <ctype.h>
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <newt.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/mount.h>
  10. #include <sys/stat.h>
  11. #include <unistd.h>
  12.  
  13. #include "devices.h"
  14. #include "fs.h"
  15. #include "install.h"
  16. #include "log.h"
  17. #include "mkswap.h"
  18. #include "perror.h"
  19. #include "run.h"
  20. #include "smb.h"
  21. #include "windows.h"
  22.  
  23. int nfsmount(const char *spec, const char *node, int *flags,
  24.          char **extra_opts, char **mount_opts);
  25.  
  26. static int selectRootPartition(struct partitionTable table, int * rootPartNum);
  27. static int fstabCmp(const void * a, const void * b);
  28. static int mkdirChain(char * chain);
  29. static int mkdirIfNone(char * directory);
  30.  
  31. int canEnableSwap = 1;
  32. int badBlocks = 0;
  33.  
  34. char * nstrdup(const char * foo) {
  35.     return foo ? strdup(foo) : NULL;
  36. }
  37.  
  38. static int fstabCmp(const void * a, const void * b) {
  39.     const struct fstabEntry * first = a;
  40.     const struct fstabEntry * second = b;
  41.  
  42.     if (first->type != second->type) {
  43.     if (first->type == PART_NFS)
  44.         return 1;
  45.     else if (second->type == PART_NFS)
  46.         return -1;
  47.     }
  48.  
  49.     return strcmp(first->mntpoint, second->mntpoint);
  50. }
  51.  
  52. void fstabSort(struct fstab * fstab) {
  53.     qsort(fstab->entries, fstab->numEntries, 
  54.       sizeof(*fstab->entries), fstabCmp);
  55. }
  56.  
  57. void initFstabEntry(struct fstabEntry * e) {
  58.     e->device = NULL;
  59.     e->netHost = NULL;
  60.     e->netPath = NULL;
  61.     e->mntpoint = NULL;
  62.     e->tagName = NULL;
  63.     e->size = 0;
  64.     e->type = PART_OTHER;
  65.     e->isMounted = 0;
  66.     e->doFormat = 0;
  67. }
  68.  
  69. newtComponent addPartitionListbox(struct partitionTable table,
  70.                      newtComponent form, int left, int top, 
  71.                      int height, int type, 
  72.                      int (*filter)(struct partition * part),
  73.                      int * numItems) {
  74.     newtComponent listbox, label;
  75.     int i;
  76.     char buf[80];
  77.  
  78.     listbox = newtListbox(left, top + 1, height, NEWT_LISTBOX_RETURNEXIT);
  79.  
  80.     label = newtLabel(left, top, "Device          Begin        End   "
  81.             "Size (k)");
  82.  
  83.     if (numItems) *numItems = 0;
  84.  
  85.     for (i = 0; i < table.count; i++) {
  86.     if (table.parts[i].type == type) {
  87.         if (!filter || filter(table.parts + i)) {
  88.         sprintf(buf, "/dev/%-5s  %9d  %9d  %9d", table.parts[i].device, 
  89.             table.parts[i].begin, table.parts[i].end, 
  90.             table.parts[i].size);
  91.         newtListboxAddEntry(listbox, buf, &table.parts[i]);
  92.  
  93.         if (numItems) (*numItems)++;
  94.         }
  95.     }
  96.     }
  97.  
  98.     newtFormAddComponents(form, label, listbox, NULL);
  99.  
  100.     return listbox;
  101. }
  102.  
  103. static int selectRootPartition(struct partitionTable table, int * rootPartNum) {
  104.     newtComponent okay, cancel, form, text, listbox, answer;
  105.     int i;
  106.     struct partition * rootPart = NULL;
  107.  
  108.     for (i = 0; i < table.count; i++) 
  109.     if (table.parts[i].type == PART_EXT2) break;
  110.  
  111.     if (i == table.count) {
  112.     newtWinMessage("Select Root", "Ok",
  113.             "You don't have any Linux native partitions "
  114.             "defined. You must return to repartition "
  115.             "your hard drive.");
  116.     
  117.         return INST_CANCEL;
  118.     }
  119.  
  120.     *rootPartNum = i;
  121.  
  122.     newtCenteredWindow(64, 19, "Select Root Partition");
  123.     text = newtTextbox(1, 1, 62, 4, NEWT_TEXTBOX_WRAP);
  124.     newtTextboxSetText(text, "The root partition forms the base of your Linux "
  125.                "filesystem. It must hold everything necessary for "
  126.                "booting and initializing your system. What partition "
  127.                "would you like to use for the root filesystem?");
  128.     okay = newtButton(15, 15, "Ok");
  129.     cancel = newtButton(38, 15, "Cancel");
  130.  
  131.     form = newtForm(NULL, NULL, 0);
  132.     listbox = addPartitionListbox(table, form, 7, 6, 7, PART_EXT2, NULL, NULL);
  133.  
  134.     newtFormAddComponents(form, text, okay, cancel, NULL);
  135.     answer = newtRunForm(form);
  136.             
  137.     if (answer != cancel) {
  138.     rootPart = newtListboxGetCurrent(listbox);
  139.     }
  140.  
  141.     newtFormDestroy(form);
  142.     newtPopWindow();
  143.  
  144.     *rootPartNum = (rootPart - table.parts);
  145.     if (!rootPart)
  146.     return INST_CANCEL;
  147.     else
  148.     return 0;
  149. }
  150.  
  151. static int badMountPoint(enum partitionTypes type, char * item) {
  152.     char * chptr = item;
  153.  
  154.     if (*chptr != '/') {
  155.     newtWinMessage("Bad Mount Point", "Ok",
  156.             "Mount points must begin with a leading /.");
  157.     return INST_ERROR;
  158.     } 
  159.  
  160.     if (*(chptr + 1) && *(chptr + strlen(chptr) - 1) == '/') {
  161.     newtWinMessage("Bad Mount Point", "Ok",
  162.             "Mount points may not end with a /.");
  163.     return INST_ERROR;
  164.     } 
  165.  
  166.     while (*chptr && isprint(*chptr)) chptr++;
  167.  
  168.     if (*chptr) {
  169.     newtWinMessage("Bad Mount Point", "Ok",
  170.             "Mount points may only printable characters.");
  171.     return INST_ERROR;
  172.     }
  173.  
  174.     if (type != PART_EXT2 && (
  175.      !strncmp(item, "/var", 4) ||
  176.      !strncmp(item, "/tmp", 4) ||
  177.      !strncmp(item, "/bin", 4) ||
  178.      !strncmp(item, "/sbin", 4) ||
  179.      !strncmp(item, "/etc", 4) ||
  180.      !strncmp(item, "/boot", 4) ||
  181.      !strncmp(item, "/dev", 4) ||
  182.      !strncmp(item, "/root", 4) ||
  183.      !strncmp(item, "/lib", 4))) {
  184.     newtWinMessage("Bad Mount Point", "Ok",
  185.             "System partitions must be on Linux Native "
  186.             "partitions.");
  187.     return INST_ERROR;
  188.     }
  189.  
  190.     if (type != PART_EXT2 && type != PART_NFS &&
  191.     !strncmp(item, "/usr", 4)) {
  192.     newtWinMessage("Bad Mount Point", "Ok",
  193.             "/usr must be on a Linux Native partition "
  194.             "or an NFS volume.");
  195.     return INST_ERROR;
  196.     }
  197.  
  198.     return 0;
  199. }
  200.  
  201. static char * restrdup(char * old, char * new) {
  202.     if (old) free(old);
  203.     if (new) return strdup(new); else return NULL;
  204. }
  205.  
  206. void nfsMountCallback(newtComponent co, void * arg) {
  207.     struct nfsMountCallbackInfo * nfsinfo = arg;
  208.     char * chptr;
  209.     char * copy;
  210.  
  211.     if (!strlen(nfsinfo->netpathVal)) {
  212.     if (strchr(nfsinfo->serverVal, ':')) {
  213.         chptr = copy = alloca(strlen(nfsinfo->serverVal) + 1);
  214.         strcpy(copy, nfsinfo->serverVal);
  215.         chptr = strchr(copy, ':');
  216.         *chptr = '\0';
  217.         chptr++;
  218.         newtEntrySet(nfsinfo->server, copy, 1);
  219.         newtEntrySet(nfsinfo->netpath, chptr, 1);
  220.     }
  221.     }
  222.  
  223.     if (nfsinfo->mntpoint) {
  224.     if (strlen(nfsinfo->netpathVal) && !strlen(nfsinfo->mntpointVal)) {
  225.         newtEntrySet(nfsinfo->mntpoint, nfsinfo->netpathVal, 1);
  226.     }
  227.     }
  228. }
  229.  
  230. int editNetMountPoint(struct fstabEntry * item) {
  231.     newtComponent form, server, path, point, okay, cancel, answer;
  232.     char * pointValue, * pathValue, * serverValue;
  233.     int done = 0;
  234.     struct nfsMountCallbackInfo nfsinfo;
  235.  
  236.     newtCenteredWindow(50, 10, "Edit Network Mount Point");
  237.  
  238.     form = newtForm(NULL, NULL, 0);
  239.  
  240.     newtFormAddComponent(form, newtLabel(1, 1, "NFS Server  :"));
  241.     newtFormAddComponent(form, newtLabel(1, 2, "NFS Path    :"));
  242.     newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
  243.  
  244.     server = newtEntry(17, 1, item->netHost, 20, &serverValue, 
  245.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  246.     path = newtEntry(17, 2, item->netPath, 20, &pathValue, 
  247.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  248.     point = newtEntry(17, 3, item->mntpoint, 20, &pointValue, 
  249.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  250.  
  251.     nfsinfo.server = server;
  252.     nfsinfo.mntpoint = point;
  253.     nfsinfo.netpath = path;
  254.  
  255.     nfsinfo.serverVal = serverValue;
  256.     nfsinfo.netpathVal = pathValue;
  257.     nfsinfo.mntpointVal = pointValue;
  258.  
  259.     newtComponentAddCallback(server, nfsMountCallback, &nfsinfo);
  260.     newtComponentAddCallback(path, nfsMountCallback, &nfsinfo);
  261.  
  262.     okay = newtButton(10, 6, "Ok");
  263.     cancel = newtButton(30, 6, "Cancel");
  264.  
  265.     newtFormAddComponents(form, server, path, point, okay, cancel, NULL);
  266.  
  267.     do {
  268.     answer = newtRunForm(form);
  269.  
  270.     if (answer == cancel) {
  271.         done = 1;
  272.     } else if (*pointValue) {
  273.         if (!badMountPoint(item->type, pointValue)) 
  274.         done = 1;
  275.     }
  276.     } while (!done);
  277.  
  278.     if (answer != cancel) {
  279.     item->mntpoint = restrdup(item->mntpoint, pointValue);
  280.     item->netPath = restrdup(item->netPath, pathValue);
  281.     item->netHost = restrdup(item->netHost, serverValue);
  282.  
  283.     if (item->device) free(item->device);
  284.     item->device = malloc(strlen(pathValue) + strlen(serverValue) + 5);
  285.     sprintf(item->device, "%s:%s", serverValue, pathValue);
  286.     }
  287.  
  288.     newtPopWindow();
  289.  
  290.     if (answer == cancel)
  291.     return INST_CANCEL;
  292.     return 0;
  293. }        
  294.  
  295. static void editDeviceMountPoint(struct fstabEntry * item) {
  296.     newtComponent form, entry, okay, cancel, clear, answer;
  297.     char buf[50];
  298.     char * entryValue;
  299.     int done = 0;
  300.  
  301.     newtCenteredWindow(50, 10, "Edit Mount Point");
  302.  
  303.     form = newtForm(NULL, NULL, 0);
  304.  
  305.     strcpy(buf,"Device      : /dev/");
  306.     strcat(buf, item->device);
  307.     newtFormAddComponent(form, newtLabel(1, 1, buf));
  308.     newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
  309.  
  310.     entry = newtEntry(17, 3, item->mntpoint, 20, &entryValue, 
  311.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  312.  
  313.     okay = newtButton(5, 6, "Ok");
  314.     clear = newtButton(20, 6, "Clear");
  315.     cancel = newtButton(35, 6, "Cancel");
  316.  
  317.     newtFormAddComponents(form, entry, okay, clear, cancel, NULL);
  318.  
  319.     do {
  320.     newtFormSetCurrent(form, entry);
  321.     answer = newtRunForm(form);
  322.  
  323.     if (answer == clear)
  324.         newtEntrySet(entry, "", 1);
  325.     else if (answer == cancel || !*entryValue) {
  326.         done = 1;
  327.     } else if (*entryValue) {
  328.         if (!badMountPoint(item->type, entryValue)) 
  329.         done = 1;
  330.     }
  331.     } while (!done);
  332.  
  333.     if (answer != cancel) {
  334.     item->mntpoint = restrdup(item->mntpoint, entryValue);
  335.     }
  336.  
  337.     newtPopWindow();
  338. }        
  339.  
  340. void freeFstabEntry( struct fstabEntry *e ) {
  341.         if (e->mntpoint) free(e->mntpoint);
  342.     if (e->device)   free(e->device);
  343.     if (e->netPath)  free(e->netPath);
  344.     if (e->netHost)  free(e->netHost);
  345.  
  346. }
  347.  
  348. void freeFstab(struct fstab fstab) {
  349.     int i;
  350.  
  351.     for (i = 0; i < fstab.numEntries; i++) {
  352.     freeFstabEntry( &fstab.entries[i] );
  353.     }
  354.  
  355.     if (fstab.numEntries) free(fstab.entries);
  356. }
  357.  
  358. struct fstab copyFstab(struct fstab * fstab) {
  359.     struct fstab newfstab;
  360.     int i, j;
  361.  
  362.     if (!fstab->numEntries) {
  363.     newfstab.numEntries = 0;
  364.     newfstab.entries = malloc(1);
  365.     return newfstab;
  366.     }
  367.  
  368.     /* duplicate the current fstab */
  369.     newfstab.numEntries = fstab->numEntries;
  370.     newfstab.entries = malloc(fstab->numEntries * sizeof(struct fstabEntry));
  371.     for (i = j = 0; i < newfstab.numEntries; i++) {
  372.     if (fstab->entries[i].mntpoint) {
  373.         newfstab.entries[j] = fstab->entries[i];
  374.         newfstab.entries[j].mntpoint = nstrdup(fstab->entries[i].mntpoint);
  375.         newfstab.entries[j].device = nstrdup(fstab->entries[i].device);
  376.         newfstab.entries[j].netPath = nstrdup(fstab->entries[i].netPath);
  377.         newfstab.entries[j].netHost = nstrdup(fstab->entries[i].netHost);
  378.         j++;
  379.     }
  380.     }
  381.  
  382.     newfstab.numEntries = j;
  383.  
  384.     /* return the memory we don't actually need */
  385.     newfstab.entries = realloc(newfstab.entries, j * sizeof(struct fstabEntry));
  386.  
  387.     return newfstab;
  388. }
  389.  
  390. int setupMountTable(struct partitionTable table, struct fstab * finalFstab,
  391.             struct netInterface * intf, struct netConfig * netc,
  392.             struct driversLoaded ** dl) {
  393.     int rootPartNum = -1;
  394.     int rc, hasdups;
  395.     newtComponent f, okay, text, listbox, label, cancel, edit, answer;
  396.     newtComponent addnfs;
  397.     char buf[80];
  398.     int i, j, numMountable, numLinux;
  399.     int partNum;
  400.     struct fstab fstab;
  401.     int fstabNum;
  402.     struct fstabEntry entry, * curr;
  403.     int * fstabEntNum, * numptr;
  404.     static int firstTime = 1;
  405.     const char * basicFormat = "%-10s  %14s  %-20s %-18s";
  406.     const char * devFormat = "/dev/%-5s  %14d  %-20s %-18s";
  407.     const char * nfsFormat = "%-27s %-20s %-18s";
  408.  
  409.     fstab = copyFstab(finalFstab);
  410.  
  411.     if (firstTime) {
  412.     /* First, make them pick a root partition */
  413.     if ((rc = selectRootPartition(table, &rootPartNum))) {
  414.         freeFstab(fstab);
  415.         return rc;
  416.     }
  417.     firstTime = 0;
  418.  
  419.     for (i = partNum = 0; i < table.count; i++) {
  420.         if (i == rootPartNum) {
  421.         initFstabEntry(&entry);
  422.         entry.device = strdup(table.parts[i].device);
  423.         entry.size = table.parts[i].size;
  424.         entry.type = table.parts[i].type;
  425.         entry.tagName = table.parts[i].tagName;
  426.         entry.mntpoint = strdup("/");
  427.         addFstabEntry(&fstab, entry);
  428.         break;
  429.         }
  430.     }
  431.  
  432.     freeFstab(*finalFstab);
  433.     *finalFstab = copyFstab(&fstab);
  434.     }    
  435.  
  436.     /* If only one mountable partition exists, it would have been set up
  437.        as root above so we can stop here */
  438.     numLinux = numMountable = 0;
  439.     for (i = partNum = 0; i < table.count; i++) {
  440.     if (table.parts[i].type == PART_EXT2)
  441.         numMountable++, numLinux++;
  442.     else if (table.parts[i].type == PART_DOS ||
  443.              table.parts[i].type == PART_HPFS)
  444.         numMountable++;
  445.     }
  446.     if (!numMountable) {
  447.     errorWindow("You don't have any mountable partitions!");
  448.     return INST_ERROR;
  449.     } else if (!numLinux) {
  450.     errorWindow("You don't have any Linux partitions available!");
  451.     return INST_ERROR;
  452.     } else if (numMountable == 1)
  453.     return 0;
  454.  
  455.     newtCenteredWindow(75, 19, "Partition Disk");
  456.  
  457.     f = newtForm(NULL, NULL, 0);
  458.     text = newtTextbox(1, 1, 72, 4, NEWT_TEXTBOX_WRAP);
  459.     newtTextboxSetText(text, "You may now mount other partitions within "
  460.                "your filesystem. Many users like to use separate "
  461.                "partitions for /usr and /home for example. You may "
  462.                "also mount your DOS or OS/2 partitions to make them "
  463.                "visible to Linux.");
  464.  
  465.     okay = newtButton(6, 15, "Ok");
  466.     addnfs = newtButton(20, 15, "Add NFS");
  467.     edit = newtButton(38, 15, "Edit");
  468.     cancel = newtButton(54, 15, "Cancel");
  469.  
  470.     sprintf(buf, basicFormat, "Device", "Size", "Partition type", 
  471.         "Mount point");
  472.     label = newtLabel(1, 5, buf);
  473.  
  474.     listbox = newtListbox(1, 6, 8, NEWT_LISTBOX_RETURNEXIT);
  475.  
  476.     fstabEntNum = malloc(table.count * sizeof(*fstabEntNum));
  477.  
  478.     for (i = partNum = 0; i < table.count; i++) {
  479.     if (table.parts[i].type == PART_EXT2 || 
  480.         table.parts[i].type == PART_DOS ||
  481.         table.parts[i].type == PART_HPFS) {
  482.  
  483.         for (j = 0; j < fstab.numEntries; j++) 
  484.         if (!strcmp(table.parts[i].device, fstab.entries[j].device))
  485.             break;
  486.  
  487.         if (j < fstab.numEntries) {
  488.         fstabNum = j;
  489.         } else {
  490.         initFstabEntry(&entry);
  491.         entry.device = strdup(table.parts[i].device);
  492.         entry.size = table.parts[i].size;
  493.         entry.type = table.parts[i].type;
  494.         entry.tagName = table.parts[i].tagName;
  495.         fstabNum = addFstabEntry(&fstab, entry);
  496.         }
  497.  
  498.         sprintf(buf, devFormat, table.parts[i].device, 
  499.             table.parts[i].size, table.parts[i].tagName, 
  500.             fstab.entries[fstabNum].mntpoint ? 
  501.             fstab.entries[fstabNum].mntpoint : "");
  502.         fstabEntNum[partNum] = fstabNum;
  503.         newtListboxAddEntry(listbox, buf, fstabEntNum + partNum);
  504.         partNum++;
  505.     } 
  506.     }
  507.  
  508.     newtFormAddComponents(f, text, label, listbox, okay, addnfs, edit, cancel, 
  509.                 NULL);
  510.  
  511.     do { 
  512.     answer = newtRunForm(f);
  513.     if (answer == listbox || answer == edit) {
  514.         numptr = newtListboxGetCurrent(listbox);
  515.         curr = fstab.entries + *numptr;
  516.  
  517.         if (curr->type == PART_NFS) {
  518.         editNetMountPoint(curr);
  519.         sprintf(buf, nfsFormat, curr->device, curr->tagName,
  520.             curr->mntpoint);
  521.         } else {
  522.         editDeviceMountPoint(curr);
  523.         sprintf(buf, devFormat, curr->device, curr->size, 
  524.             curr->tagName, curr->mntpoint ? curr->mntpoint : "");
  525.         }
  526.  
  527.         newtListboxSetEntry(listbox, numptr - fstabEntNum, buf);
  528.     } else if (answer == addnfs) {
  529.         initFstabEntry(&entry);
  530.         entry.type = PART_NFS;
  531.         entry.tagName = "NFS Mount";
  532.         entry.device = NULL;
  533.         entry.mntpoint = NULL;
  534.  
  535.         if (!intf->isConfigured) {
  536.         rc = bringUpNetworking(intf, netc, dl);
  537.         } else {
  538.         rc = 0;
  539.         }
  540.  
  541.         if (!rc && !editNetMountPoint(&entry)) {
  542.         fstabNum = addFstabEntry(&fstab, entry);
  543.         fstabEntNum = realloc(fstabEntNum, 
  544.                       sizeof(*fstabEntNum) * fstabNum);
  545.  
  546.         sprintf(buf, nfsFormat, entry.device, entry.tagName,
  547.             entry.mntpoint);
  548.  
  549.         newtListboxAddEntry(listbox, buf, fstabEntNum + fstabNum);
  550.         /*newtListboxSetCurrent(listbox, fstabNum);*/
  551.         }
  552.     } else if (answer != cancel) {
  553.         answer = okay;
  554.         for (i = 0; i < fstab.numEntries; i++) 
  555.         if (fstab.entries[i].mntpoint &&
  556.             !strcmp(fstab.entries[i].mntpoint, "/")) break;
  557.  
  558.         if (i == fstab.numEntries) {
  559.         newtWinMessage("No Root Partition", "Ok",
  560.                 "You must assign a root (/) partition for the "
  561.                 "install to proceed.");
  562.         answer = NULL;
  563.         continue;
  564.         }
  565.  
  566.         hasdups = 0;
  567.         for (i = 0; i < fstab.numEntries; i++) 
  568.         for (j = i + 1; j < fstab.numEntries; j++) 
  569.             if (fstab.entries[i].type != PART_SWAP &&
  570.             fstab.entries[i].mntpoint &&
  571.                 fstab.entries[j].mntpoint &&
  572.             !strcmp(fstab.entries[i].mntpoint,
  573.                         fstab.entries[j].mntpoint))
  574.             hasdups = 1;
  575.  
  576.         if (hasdups) {
  577.         newtWinMessage("Duplicate Mounts", "Ok",
  578.                 "You may not use the same mount point multiple "
  579.                 "times.");
  580.         answer = NULL;
  581.         }
  582.     }
  583.     } while (answer != okay && answer != cancel);
  584.  
  585.     newtFormDestroy(f);
  586.     newtPopWindow();
  587.  
  588.     free(fstabEntNum);
  589.  
  590.     if (answer == cancel) { 
  591.     freeFstab(fstab);
  592.     return INST_CANCEL;
  593.     }
  594.  
  595.     freeFstab(*finalFstab);
  596.     *finalFstab = copyFstab(&fstab);
  597.     freeFstab(fstab);
  598.  
  599.     /* Sort by mount point. This makes mounting everything in the proper
  600.        order trivial */
  601.  
  602.     fstabSort(finalFstab);
  603.  
  604.     return 0;
  605. }
  606.  
  607. static int mkExt2Filesystem(char * dev) {
  608.     char * mke2fsargs[] = { "mke2fs", NULL, NULL, NULL};
  609.     int rc;
  610.     char message[80];
  611.  
  612.     mke2fsargs[1] = alloca(strlen(dev) + 6);
  613.     strcpy(mke2fsargs[1], "/tmp/");
  614.     strcat(mke2fsargs[1], dev);
  615.  
  616.     if (badBlocks)
  617.     mke2fsargs[2] = "-c";
  618.  
  619.     sprintf(message, "Making ext2 filesystem on /dev/%s...", dev);
  620.     winStatus(45, 3, "Running", message);
  621.  
  622.     devMakeInode(dev, mke2fsargs[1]);
  623.     rc = runProgram(RUN_LOG, "/usr/bin/mke2fs", mke2fsargs);
  624.     devRemoveInode(mke2fsargs[1]);
  625.  
  626.     newtPopWindow();
  627.  
  628.     if (rc)
  629.     return INST_ERROR;
  630.     else
  631.     return 0;
  632. }
  633.  
  634. int queryFormatFilesystems(struct fstab * fstab) {
  635.     newtComponent form, checkList, okay, cancel, sb, text, answer;
  636.     newtComponent checkbox;
  637.     char * states;
  638.     char doCheck = ' ';
  639.     newtComponent * checks;
  640.     char buf[80];
  641.     int i, top;
  642.  
  643.     newtCenteredWindow(57, 19, "Format Partitions");
  644.  
  645.     form = newtForm(NULL, NULL, 0);
  646.  
  647.     if (fstab->numEntries > 4) 
  648.     sb = newtVerticalScrollbar(47, 7, 4, 9, 10);
  649.     else
  650.     sb = NULL;
  651.  
  652.     checkList = newtForm(sb, NULL, 0);
  653.     newtFormSetHeight(checkList, 4);
  654.  
  655.     if (sb)
  656.     newtFormAddComponent(checkList, sb);
  657.  
  658.     text = newtTextbox(1, 1, 55, 6, NEWT_TEXTBOX_WRAP);
  659.     newtTextboxSetText(text, "What partitions would you like to "
  660.                "format? We strongly suggest formatting all of the "
  661.                "system partitions, including /, /usr, and /var. There "
  662.                "is no need to format /home or /usr/local if they "
  663.                "have already been configured during a previous "
  664.                "install.");
  665.  
  666.     checks = alloca(sizeof(newtComponent) * fstab->numEntries);
  667.     states = alloca(sizeof(char) * fstab->numEntries);
  668.     for (i = 0, top = 0; i < fstab->numEntries; i++) {
  669.     if (fstab->entries[i].doFormat)
  670.         states[i] = '*';
  671.     else
  672.         states[i] = ' ';
  673.  
  674.     if (fstab->entries[i].type == PART_EXT2) {
  675.         sprintf(buf, "/dev/%-5s  %-33s", fstab->entries[i].device, 
  676.            fstab->entries[i].mntpoint);
  677.         checks[i] = newtCheckbox(3, 7 + top++, buf, states[i], NULL, 
  678.                      &states[i]);
  679.         newtFormAddComponent(checkList, checks[i]);
  680.     } else {
  681.         checks[i] = NULL;
  682.     }
  683.     }
  684.  
  685.     okay = newtButton(12, 14, "Ok");
  686.     cancel = newtButton(34, 14, "Cancel");
  687.     checkbox = newtCheckbox(10, 12, "Check for bad blocks during format",
  688.                 badBlocks ? '*' : ' ', NULL, &doCheck);
  689.     
  690.     newtFormAddComponents(form, text, checkList, checkbox, okay, cancel, NULL);
  691.  
  692.     answer = newtRunForm(form);
  693.  
  694.     newtFormDestroy(form);
  695.     newtPopWindow();
  696.  
  697.     if (answer == cancel) return INST_CANCEL;
  698.  
  699.     for (i = 0; i < fstab->numEntries; i++) {
  700.         if (states[i] != ' ') 
  701.         fstab->entries[i].doFormat = 1; 
  702.     }
  703.  
  704.     if (doCheck == ' ')
  705.     badBlocks = 0;
  706.     else
  707.     badBlocks = 1;
  708.  
  709.     return 0;
  710. }
  711.  
  712. int formatFilesystems(struct fstab * fstab) {
  713.     int i;
  714.  
  715.     for (i = 0; i < fstab->numEntries; i++) {
  716.         if (fstab->entries[i].doFormat)
  717.         mkExt2Filesystem(fstab->entries[i].device);
  718.     }
  719.  
  720.     return 0;
  721. }
  722.  
  723. int doMount(char * dev, char * where, char * fs, int rdonly, int istty) {
  724.     return doPwMount(dev, where, fs, rdonly, istty, NULL, NULL);
  725. }
  726.  
  727. int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty,
  728.         char * acct, char * pw) { 
  729.     char * buf = NULL;
  730.     int isnfs = 0;
  731.     char * mount_opt = NULL;
  732.     long int flag;
  733.     char * chptr;
  734.  
  735.     if (!strcmp(fs, "nfs")) isnfs = 1;
  736.  
  737.     logMessage("mounting %s on %s as type %s", dev, where, fs);
  738.  
  739.     if (testing) {
  740.     newtWinMessage("Test mount", "Ok", "I would mount /dev/%s on %s",
  741.         "using a(n) %s filesystem.", dev, where, fs);
  742.     } else if (!strcmp(fs, "smb")) {
  743.     mkdirChain(where);
  744.  
  745.     if (!acct) acct = "guest";
  746.     if (!pw) pw = "";
  747.  
  748.     buf = alloca(strlen(dev) + 1);
  749.     strcpy(buf, dev);
  750.     chptr = buf;
  751.     while (*chptr && *chptr != ':') chptr++;
  752.     if (!*chptr) {
  753.         logMessage("bad smb mount point %s", where);
  754.         return 0;
  755.     } 
  756.     
  757.     *chptr = '\0';
  758.     chptr++;
  759.  
  760. #ifdef __i386__
  761.     logMessage("mounting smb filesystem from %s path %s on %s",
  762.             buf, chptr, where);
  763.     return smbmount(buf, chptr, acct, pw, "localhost", where);
  764. #else 
  765.     errorWindow("smbfs only works on Intel machines");
  766. #endif
  767.     } else {
  768.     mkdirChain(where);
  769.  
  770.       if (!isnfs && *dev == '/') {
  771.         buf = dev;
  772.     } else if (!isnfs) {
  773.         buf = alloca(200);
  774.         strcpy(buf, "/tmp/");
  775.         strcat(buf, dev);
  776.  
  777.         if (devMakeInode(dev, buf)) return 1;
  778.     } else {
  779.         char * junk = NULL;
  780.         int morejunk = 0;
  781.  
  782.         buf = dev;
  783.         logMessage("calling nfsmount(%s, %s, &morejunk, &junk, &mount_opt)",
  784.             buf, where);
  785.  
  786.         if (nfsmount(buf, where, &morejunk, &junk, &mount_opt))
  787.         logMessage("\tnfsmount returned non-zero");
  788.     }
  789.  
  790.     flag = MS_MGC_VAL;
  791.     if (rdonly)
  792.         flag |= MS_RDONLY;
  793.     
  794.     logMessage("calling mount(%s, %s, %s, %ld, %p)", buf, where, fs, 
  795.             flag, mount_opt);
  796.  
  797.     if (mount(buf, where, fs, flag, mount_opt)) {
  798.         if (istty) {
  799.         fprintf(stderr, "mount failed: %s\n", strerror(errno));
  800.         } else {
  801.         newtWinMessage("Error", "Ok", perrorstr("mount failed"));
  802.         }
  803.         return 1;
  804.     }
  805.  
  806.     if (!isnfs) devRemoveInode(buf);
  807.     }
  808.  
  809.     return 0;
  810. }
  811.  
  812. int mountFilesystems(struct fstab * fstab) {
  813.     int i;
  814.     char buf[1000];
  815.  
  816.     /* don't bother mounting odd (non-ext2) filesystems - we don't need
  817.        them for installs */
  818.  
  819.     /* what about NFS? we should probably mount them to check mount integrity,
  820.        but we don't know if networking is working well enough for us to do
  821.        this */
  822.    
  823.     chdir("/");
  824.  
  825.     for (i = 0; i < fstab->numEntries; i++) {
  826.     strcpy(buf, "/mnt");
  827.     strcat(buf, fstab->entries[i].mntpoint);
  828.  
  829.     if (fstab->entries[i].type == PART_EXT2 ||
  830.         fstab->entries[i].type == PART_NFS ) {
  831.         if (fstab->entries[i].type == PART_EXT2 &&
  832.         !doMount(fstab->entries[i].device, buf, "ext2", 0, 0))
  833.         fstab->entries[i].isMounted = 1;
  834.         else if (fstab->entries[i].type == PART_NFS &&
  835.         !doMount(fstab->entries[i].device, buf, "nfs", 0, 0))
  836.         fstab->entries[i].isMounted = 1;
  837.         else {
  838.         logMessage("unmounting all filesystems due to mount error");
  839.         umountFilesystems(fstab);
  840.         return INST_ERROR;
  841.         }
  842.     } else {
  843.         logMessage("creating directory %s", buf);
  844.         mkdirChain(buf);
  845.     }
  846.     }
  847.  
  848.     return 0;
  849. }
  850.  
  851. int umountFilesystems(struct fstab * fstab) {
  852.     char buf[1000];
  853.     int i;
  854.     int olderrno;
  855.  
  856.     logMessage("unmounting all filesystems");
  857.  
  858.     chdir("/");
  859.  
  860.     if (testing) return 0;
  861.  
  862.     for (i = fstab->numEntries - 1; i >= 0; i--) {
  863.     if (fstab->entries[i].isMounted) {
  864.         strcpy(buf, "/mnt");
  865.         strcat(buf, fstab->entries[i].mntpoint);
  866.  
  867.         fstab->entries[i].isMounted = 0;
  868.         if (umount(buf)) {
  869.         olderrno = errno;
  870.         logMessage("error unmounting %s: %s\n", buf, strerror(errno));
  871.         errno = olderrno;
  872.         errorWindow("error unmounting filesystem: %s");
  873.         }
  874.     }    
  875.     }
  876.  
  877.     return 0;
  878. }
  879.  
  880. static int mkdirChain(char * origChain) {
  881.     char * chain;
  882.     char * chptr;
  883.  
  884.     chain = alloca(strlen(origChain) + 1);
  885.     strcpy(chain, origChain);
  886.     chptr = chain;
  887.  
  888.     if (testing) return 0;
  889.  
  890.     while ((chptr = strchr(chptr, '/'))) {
  891.     *chptr = '\0';
  892.     if (mkdirIfNone(chain)) {
  893.         *chptr = '/';
  894.         return INST_ERROR;
  895.     }
  896.  
  897.     *chptr = '/';
  898.     chptr++;
  899.     }
  900.  
  901.     if (mkdirIfNone(chain))
  902.     return INST_ERROR;
  903.  
  904.     return 0;
  905. }
  906.  
  907. static int mkdirIfNone(char * directory) {
  908.     int rc, mkerr;
  909.     char * chptr;
  910.  
  911.     /* If the file exists it *better* be a directory -- I'm not going to
  912.        actually check or anything */
  913.     if (!access(directory, X_OK)) return 0;
  914.  
  915.     /* if the path is '/' we get ENOFILE not found" from mkdir, rather
  916.        then EEXIST which is weird */
  917.     for (chptr = directory; *chptr; chptr++)
  918.         if (*chptr != '/') break;
  919.     if (!*chptr) return 0;
  920.  
  921.     rc = mkdir(directory, 0755);
  922.     mkerr = errno;
  923.  
  924.     logMessage("creating directory %s rc = %d", directory, rc);
  925.  
  926.     if (!rc || mkerr == EEXIST) return 0;
  927.  
  928.     logMessage("    error: %s", strerror(mkerr));
  929.  
  930.     return INST_ERROR;
  931. }
  932.  
  933. int writeFstab(struct fstab * fstab) {
  934.     int i;
  935.     FILE * f;
  936.     int fd;
  937.     char * fs = NULL;
  938.     int freq = 0;
  939.     int passno = 0;
  940.     int bad;
  941.     char buf[4096];
  942.     char * chptr, * cddev = NULL;
  943.     char * devFormat = "/dev/%-18s %-23s %-7s %-15s %d %d\n";
  944.     char * nfsFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  945.     char * procFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  946.     char * options;
  947.     char * format;
  948.  
  949.     logMessage("scanning /proc/mounts for iso9660 filesystems");
  950.     fd = open("/proc/mounts", O_RDONLY);
  951.     if (fd < 0) {
  952.     logMessage("\terror opening /proc/mounts -- skipping check: %s",
  953.             strerror(errno));
  954.     } else {
  955.     i = read(fd, buf, sizeof(buf) - 1);
  956.     if (i < 0) {
  957.         logMessage("\terror reading /proc/mounts -- skipping check: %s",
  958.                 strerror(errno));
  959.     } else {
  960.         buf[i] = 0;
  961.         if ((chptr = strstr(buf, "iso9660"))) {
  962.         chptr--;
  963.  
  964.         /* skip the mount point */
  965.         while (*chptr == ' ') chptr--;
  966.         while (*chptr != ' ') chptr--;
  967.         while (*chptr == ' ') chptr--;
  968.  
  969.         chptr++;
  970.         *chptr = '\0';
  971.         while (*chptr != '/') chptr--;
  972.         cddev = strdup(chptr + 1);
  973.         
  974.         logMessage("found mounted cdrom drive %s", cddev);
  975.         }
  976.     }
  977.     }
  978.  
  979.     #ifndef __sparc__
  980.     if (!cddev) {
  981.     if (findAtapi(&cddev)) cddev = NULL;
  982.     }
  983.     #endif
  984.     if (!cddev) {
  985.     if (findSCSIcdrom(&cddev)) cddev = NULL;
  986.     }
  987.  
  988.     if (testing) {
  989.     if (cddev) free(cddev);
  990.     return 0;
  991.     }
  992.  
  993.     logMessage("touching /etc/mtab");
  994.     f = fopen("/mnt/etc/mtab", "w+");
  995.     if (!f) {
  996.     errorWindow("error touching /mnt/etc/mtab");
  997.     } else {
  998.     fclose(f);
  999.     }
  1000.  
  1001.     logMessage("creating /etc/fstab");
  1002.  
  1003.     f = fopen("/mnt/etc/fstab", "w");
  1004.     if (!f) {
  1005.     if (cddev) free(cddev);
  1006.     errorWindow("error creating /mnt/etc/fstab");
  1007.     return INST_ERROR;
  1008.     }
  1009.  
  1010.     for (i = 0; i < fstab->numEntries; i++) {
  1011.     if (!fstab->entries[i].mntpoint) continue;
  1012.  
  1013.     passno = 0;
  1014.     freq = 0;
  1015.     format = devFormat;
  1016.         options = "defaults";
  1017.  
  1018.     bad = 0;
  1019.     switch (fstab->entries[i].type) {
  1020.       case PART_EXT2:
  1021.         freq = 1;
  1022.         fs = "ext2";
  1023.         if (!strcmp(fstab->entries[i].mntpoint, "/"))
  1024.         passno = 1;
  1025.         else
  1026.         passno = 2;
  1027.       
  1028.         break;
  1029.  
  1030.       case PART_NFS:
  1031.         fs = "nfs";
  1032.         options = "ro";
  1033.         format = nfsFormat;
  1034.         break;
  1035.  
  1036.       case PART_SWAP:
  1037.         fs = "swap";
  1038.         break;
  1039.  
  1040.       case PART_DOS:
  1041.         fs = "msdos";
  1042.         break;
  1043.  
  1044.       case PART_HPFS:
  1045.         fs = "hpfs";
  1046.         break;
  1047.  
  1048.       default:
  1049.         bad = 1;
  1050.     }
  1051.  
  1052.     if (!bad)
  1053.         fprintf(f, format, fstab->entries[i].device, 
  1054.             fstab->entries[i].mntpoint, fs, options, freq, passno);
  1055.     }
  1056.  
  1057.     fprintf(f, devFormat, "fd0", "/mnt/floppy", "ext2", "noauto", 0, 0);
  1058.     if (cddev) {
  1059.     if (mkdir("/mnt/mnt/cdrom", 0755)) 
  1060.         logMessage("failed to mkdir /mnt/mnt/cdrom: %s", strerror(errno));
  1061.  
  1062.     if (symlink(cddev, "/mnt/dev/cdrom"))
  1063.         logMessage("failed to symlink /mnt/dev/cdrom: %s", strerror(errno));
  1064.  
  1065.     fprintf(f, devFormat, "cdrom", "/mnt/cdrom", "iso9660", "noauto,ro", 
  1066.         0, 0);
  1067.     free(cddev);
  1068.     }
  1069.  
  1070.     fprintf(f, procFormat, "none", "/proc", "proc", "defaults", 0, 0);
  1071.  
  1072.     fclose(f);
  1073.  
  1074.  
  1075.     return 0;
  1076. }
  1077.  
  1078. int addFstabEntry(struct fstab * fstab, struct fstabEntry entry) {
  1079.     int i;
  1080.  
  1081.     for (i = 0; i < fstab->numEntries; i++) 
  1082.     if (!strcmp(entry.device, fstab->entries[i].device))
  1083.         break;
  1084.  
  1085.     if (i == fstab->numEntries) {
  1086.     fstab->numEntries++;
  1087.     if (fstab->numEntries > 1)
  1088.         fstab->entries = realloc(fstab->entries, 
  1089.                 sizeof(entry) * fstab->numEntries);
  1090.     else
  1091.         fstab->entries = malloc(sizeof(entry));
  1092.     }
  1093.  
  1094.     fstab->entries[i] = entry;
  1095.  
  1096.     return i;
  1097. }
  1098.  
  1099. int activeSwapSpace(struct partitionTable * table, struct fstab * finalFstab) {
  1100.     newtComponent form, checkList, okay, cancel, sb, text, answer, label;
  1101.     newtComponent check, checkbox;
  1102.     char * states;
  1103.     char buf[80];
  1104.     int i, top, j, rc;
  1105.     struct fstabEntry entry;
  1106.     struct fstabEntry ** entries;
  1107.     struct fstab fstab;
  1108.     static int firstTime = 1;
  1109.     static int chkBadBlocks = 1;
  1110.     char doCheck = ' ';
  1111.  
  1112.     fstab = copyFstab(finalFstab);    
  1113.  
  1114.     form = newtForm(NULL, NULL, 0);
  1115.  
  1116.     for (i = j = 0; i < table->count; i++)
  1117.     if (table->parts[i].type == PART_SWAP)
  1118.         j++;
  1119.  
  1120.     if (!j) {
  1121.     rc = newtWinChoice("No Swap Space", "Repartition", "Continue",
  1122.                 "You don't have any swap space defined. Would "
  1123.                 "you like to continue, or repartition your disk?");
  1124.     if (rc != 1)
  1125.        return INST_CANCEL;
  1126.     
  1127.     return 0;
  1128.     }
  1129.  
  1130.     if (!kickstart) {
  1131.     newtCenteredWindow(54, 15, "Active Swap Space");
  1132.         
  1133.     if (j > 3)
  1134.         sb = newtVerticalScrollbar(47, 7, 3, 9, 10);
  1135.     else
  1136.         sb = NULL;
  1137.  
  1138.     checkList = newtForm(sb, NULL, 0);
  1139.     newtFormSetHeight(checkList, 3);
  1140.  
  1141.     if (sb)
  1142.         newtFormAddComponent(checkList, sb);
  1143.  
  1144.     text = newtTextbox(1, 1, 52, 4, NEWT_TEXTBOX_WRAP);
  1145.     newtTextboxSetText(text, "What partitions would you like to "
  1146.                "use for swap space? This will destroy any "
  1147.                "information already on the partition.");
  1148.  
  1149.     label = newtLabel(4, 5, "  Device          Begin        End   Size (k)");
  1150.  
  1151.     states = alloca(sizeof(char) * table->count);
  1152.     entries = alloca(sizeof(*entries) * table->count);
  1153.  
  1154.     for (i = 0, top = 0; i < table->count; i++) {
  1155.         if (table->parts[i].type != PART_SWAP) continue;
  1156.  
  1157.         for (j = 0; j < fstab.numEntries; j++) 
  1158.         if (!strcmp(table->parts[i].device, fstab.entries[j].device))
  1159.             break;
  1160.  
  1161.         if ((j < fstab.numEntries && fstab.entries[j].mntpoint) || 
  1162.         (firstTime && !testing))
  1163.         states[i] = '*';
  1164.         else
  1165.         states[i] = ' ';
  1166.  
  1167.         if (j < fstab.numEntries) 
  1168.         entries[i] = fstab.entries + j;
  1169.         else
  1170.         entries[i] = NULL;
  1171.  
  1172.         sprintf(buf, "/dev/%-5s  %9d  %9d  %9d", table->parts[i].device, 
  1173.             table->parts[i].begin, table->parts[i].end, 
  1174.             table->parts[i].size);
  1175.         check = newtCheckbox(2, 6 + top++, buf, states[i], NULL, 
  1176.                      &states[i]);
  1177.         newtFormAddComponent(checkList, check);
  1178.     }
  1179.  
  1180.     firstTime = 0;
  1181.  
  1182.     checkbox = newtCheckbox(2, 9, "Check for bad blocks during format",
  1183.                     chkBadBlocks ? '*' : ' ', NULL, &doCheck);
  1184.  
  1185.     okay = newtButton(9, 11, "Ok");
  1186.     cancel = newtButton(28, 11, "Cancel");
  1187.     
  1188.     newtFormAddComponents(form, text, label, checkList, checkbox, okay, 
  1189.                   cancel, NULL);
  1190.  
  1191.     answer = newtRunForm(form);
  1192.  
  1193.     newtFormDestroy(form);
  1194.     newtPopWindow();
  1195.  
  1196.     chkBadBlocks = (doCheck != ' ');
  1197.  
  1198.     if (answer == cancel) {
  1199.         freeFstab(fstab);
  1200.         return INST_CANCEL;
  1201.     }
  1202.     }
  1203.  
  1204.     for (i = 0; i < table->count; i++) {
  1205.     if (table->parts[i].type != PART_SWAP) continue;
  1206.  
  1207.         if (kickstart || states[i] != ' ') {
  1208.         if (!kickstart && entries[i])
  1209.         entries[i]->mntpoint = strdup("swap");
  1210.         else {
  1211.         initFstabEntry(&entry);
  1212.         entry.device = strdup(table->parts[i].device);
  1213.         entry.size = table->parts[i].size;
  1214.         entry.type = table->parts[i].type;
  1215.         entry.tagName = table->parts[i].tagName;
  1216.         entry.mntpoint = strdup("swap");
  1217.  
  1218.         addFstabEntry(&fstab, entry);
  1219.         }
  1220.     } else if (entries[i]) {
  1221.         free(entries[i]->mntpoint);
  1222.         entries[i]->mntpoint = NULL;
  1223.     }
  1224.     }
  1225.  
  1226.     if (canEnableSwap) {
  1227.     for (i = 0; i < fstab.numEntries; i++) {
  1228.         if (fstab.entries[i].type == PART_SWAP &&
  1229.         fstab.entries[i].mntpoint) {
  1230.         enableswap(fstab.entries[i].device, 0, chkBadBlocks);
  1231.         canEnableSwap = 0;
  1232.         }
  1233.     }
  1234.     }
  1235.  
  1236.     freeFstab(*finalFstab);
  1237.     *finalFstab = copyFstab(&fstab);
  1238.     freeFstab(fstab);
  1239.  
  1240.     return 0;
  1241. }
  1242.