home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / install / fs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-02  |  19.9 KB  |  811 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 "intl.h"
  17. #include "log.h"
  18. #include "mkswap.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 fstabCmp(const void * a, const void * b);
  27. static int mkdirChain(char * chain);
  28. static int mkdirIfNone(char * directory);
  29.  
  30. int badBlocks = 0;
  31.  
  32. char * nstrdup(const char * foo) {
  33.     return foo ? strdup(foo) : NULL;
  34. }
  35.  
  36. static int fstabCmp(const void * a, const void * b) {
  37.     const struct fstabEntry * first = a;
  38.     const struct fstabEntry * second = b;
  39.  
  40.     if (first->type != second->type) {
  41.     if (first->type == PART_NFS)
  42.         return 1;
  43.     else if (second->type == PART_NFS)
  44.         return -1;
  45.     }
  46.  
  47.     return strcmp(first->mntpoint, second->mntpoint);
  48. }
  49.  
  50. void fstabSort(struct fstab * fstab) {
  51.     qsort(fstab->entries, fstab->numEntries, 
  52.       sizeof(*fstab->entries), fstabCmp);
  53. }
  54.  
  55. void initFstabEntry(struct fstabEntry * e) {
  56.     e->device = NULL;
  57.     e->netHost = NULL;
  58.     e->netPath = NULL;
  59.     e->mntpoint = NULL;
  60.     e->tagName = NULL;
  61.     e->size = 0;
  62.     e->type = PART_OTHER;
  63.     e->isMounted = 0;
  64.     e->doFormat = 0;
  65. }
  66.  
  67. void addPartitionListbox(struct partitionTable table, int maxHeight, int type, 
  68.              int (*filter)(struct partition * part),
  69.              int * numItems, newtGrid * gridPtr, 
  70.              newtComponent * listboxPtr) {
  71.     newtComponent listbox, label;
  72.     int i, count;
  73.     char buf[80];
  74.  
  75.     count = 0;
  76.     for (i = 0; i < table.count; i++) 
  77.     if (table.parts[i].type & type)
  78.         if (!filter || filter(table.parts + i)) count++;
  79.  
  80.     *listboxPtr = listbox = newtListbox(-1, -1, 
  81.                     count < maxHeight ? count : maxHeight,
  82.     NEWT_FLAG_RETURNEXIT | (count > maxHeight ? NEWT_FLAG_SCROLL : 0));
  83.  
  84.     label = newtLabel(-1, -1, "Device       Size (k)");
  85.  
  86.     if (numItems) *numItems = 0;
  87.  
  88.     for (i = 0; i < table.count; i++) {
  89.     if (table.parts[i].type & type) {
  90.         if (!filter || filter(table.parts + i)) {
  91.         sprintf(buf, "/dev/%-5s  %9d", table.parts[i].device, 
  92.             table.parts[i].size);
  93.         newtListboxAddEntry(listbox, buf, &table.parts[i]);
  94.  
  95.         if (numItems) (*numItems)++;
  96.         }
  97.     }
  98.     }
  99.  
  100.     /* using VStacked right here adds too much padding */
  101.     *gridPtr = newtCreateGrid(1, 2);
  102.     newtGridSetField(*gridPtr, 0, 0, NEWT_GRID_COMPONENT, label,
  103.              0, 0, 0, 0, 0, 0);
  104.     newtGridSetField(*gridPtr, 0, 1, NEWT_GRID_COMPONENT, listbox,
  105.              0, 0, 0, 0, 0, 0);
  106. }
  107.  
  108. static int badMountPoint(unsigned int type, char * item) {
  109.     char * chptr = item;
  110.  
  111.     if (*chptr != '/') {
  112.     newtWinMessage(_("Bad Mount Point"), _("Ok"),
  113.             _("Mount points must begin with a leading /."));
  114.     return INST_ERROR;
  115.     } 
  116.  
  117.     if (*(chptr + 1) && *(chptr + strlen(chptr) - 1) == '/') {
  118.     newtWinMessage(_("Bad Mount Point"), _("Ok"),
  119.             _("Mount points may not end with a /."));
  120.     return INST_ERROR;
  121.     } 
  122.  
  123.     while (*chptr && isprint(*chptr)) chptr++;
  124.  
  125.     if (*chptr) {
  126.     newtWinMessage(_("Bad Mount Point"), _("Ok"),
  127.             _("Mount points may only printable characters."));
  128.     return INST_ERROR;
  129.     }
  130.  
  131.     if (type != PART_EXT2 && (
  132.      !strncmp(item, "/var", 4) ||
  133.      !strncmp(item, "/tmp", 4) ||
  134.      !strncmp(item, "/bin", 4) ||
  135.      !strncmp(item, "/sbin", 4) ||
  136.      !strncmp(item, "/etc", 4) ||
  137.      !strncmp(item, "/boot", 4) ||
  138.      !strncmp(item, "/dev", 4) ||
  139.      !strncmp(item, "/root", 4) ||
  140.      !strncmp(item, "/lib", 4))) {
  141.     newtWinMessage(_("Bad Mount Point"), _("Ok"),
  142.             _("System partitions must be on Linux Native "
  143.               "partitions."));
  144.     return INST_ERROR;
  145.     }
  146.  
  147.     if (type != PART_EXT2 && type != PART_NFS &&
  148.     !strncmp(item, "/usr", 4)) {
  149.     newtWinMessage(_("Bad Mount Point"), _("Ok"),
  150.             _("/usr must be on a Linux Native partition "
  151.               "or an NFS volume."));
  152.     return INST_ERROR;
  153.     }
  154.  
  155.     return 0;
  156. }
  157.  
  158. static char * restrdup(char * old, char * new) {
  159.     if (old) free(old);
  160.     if (new) return strdup(new); else return NULL;
  161. }
  162.  
  163. void nfsMountCallback(newtComponent co, void * arg) {
  164.     struct nfsMountCallbackInfo * nfsinfo = arg;
  165.     char * chptr;
  166.     char * copy;
  167.  
  168.     if (!strlen(nfsinfo->netpathVal)) {
  169.     if (strchr(nfsinfo->serverVal, ':')) {
  170.         chptr = copy = alloca(strlen(nfsinfo->serverVal) + 1);
  171.         strcpy(copy, nfsinfo->serverVal);
  172.         chptr = strchr(copy, ':');
  173.         *chptr = '\0';
  174.         chptr++;
  175.         newtEntrySet(nfsinfo->server, copy, 1);
  176.         newtEntrySet(nfsinfo->netpath, chptr, 1);
  177.     }
  178.     }
  179.  
  180.     if (nfsinfo->mntpoint) {
  181.     if (strlen(nfsinfo->netpathVal) && !strlen(nfsinfo->mntpointVal)) {
  182.         newtEntrySet(nfsinfo->mntpoint, nfsinfo->netpathVal, 1);
  183.     }
  184.     }
  185. }
  186.  
  187. int editNetMountPoint(struct fstabEntry * item) {
  188.     newtComponent form, server, path, point, okay, cancel, answer;
  189.     char * pointValue, * pathValue, * serverValue;
  190.     int done = 0;
  191.     struct nfsMountCallbackInfo nfsinfo;
  192.  
  193.     newtCenteredWindow(50, 10, _("Edit Network Mount Point"));
  194.  
  195.     form = newtForm(NULL, NULL, 0);
  196.  
  197.     newtFormAddComponent(form, newtLabel(1, 1, "NFS Server  :"));
  198.     newtFormAddComponent(form, newtLabel(1, 2, "NFS Path    :"));
  199.     newtFormAddComponent(form, newtLabel(1, 3, "Mount point :"));
  200.  
  201.     server = newtEntry(17, 1, item->netHost, 20, &serverValue, 
  202.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  203.     path = newtEntry(17, 2, item->netPath, 20, &pathValue, 
  204.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  205.     point = newtEntry(17, 3, item->mntpoint, 20, &pointValue, 
  206.               NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT);
  207.  
  208.     nfsinfo.server = server;
  209.     nfsinfo.mntpoint = point;
  210.     nfsinfo.netpath = path;
  211.  
  212.     nfsinfo.serverVal = serverValue;
  213.     nfsinfo.netpathVal = pathValue;
  214.     nfsinfo.mntpointVal = pointValue;
  215.  
  216.     newtComponentAddCallback(server, nfsMountCallback, &nfsinfo);
  217.     newtComponentAddCallback(path, nfsMountCallback, &nfsinfo);
  218.  
  219.     okay = newtButton(10, 6, _("Ok"));
  220.     cancel = newtButton(30, 6, _("Cancel"));
  221.  
  222.     newtFormAddComponents(form, server, path, point, okay, cancel, NULL);
  223.  
  224.     do {
  225.     answer = newtRunForm(form);
  226.  
  227.     if (answer == cancel) {
  228.         done = 1;
  229.     } else if (*pointValue) {
  230.         if (!badMountPoint(item->type, pointValue)) 
  231.         done = 1;
  232.     }
  233.     } while (!done);
  234.  
  235.     if (answer != cancel) {
  236.     item->mntpoint = restrdup(item->mntpoint, pointValue);
  237.     item->netPath = restrdup(item->netPath, pathValue);
  238.     item->netHost = restrdup(item->netHost, serverValue);
  239.  
  240.     if (item->device) free(item->device);
  241.     item->device = malloc(strlen(pathValue) + strlen(serverValue) + 5);
  242.     sprintf(item->device, "%s:%s", serverValue, pathValue);
  243.     }
  244.  
  245.     newtPopWindow();
  246.  
  247.     if (answer == cancel)
  248.     return INST_CANCEL;
  249.     return 0;
  250. }        
  251.  
  252. void freeFstabEntry( struct fstabEntry *e ) {
  253.         if (e->mntpoint) free(e->mntpoint);
  254.     if (e->device)   free(e->device);
  255.     if (e->netPath)  free(e->netPath);
  256.     if (e->netHost)  free(e->netHost);
  257.  
  258. }
  259.  
  260. void freeFstab(struct fstab fstab) {
  261.     int i;
  262.  
  263.     for (i = 0; i < fstab.numEntries; i++) {
  264.     freeFstabEntry( &fstab.entries[i] );
  265.     }
  266.  
  267.     if (fstab.numEntries) free(fstab.entries);
  268. }
  269.  
  270. struct fstab copyFstab(struct fstab * fstab) {
  271.     struct fstab newfstab;
  272.     int i, j;
  273.  
  274.     if (!fstab->numEntries) {
  275.     newfstab.numEntries = 0;
  276.     newfstab.entries = malloc(1);
  277.     return newfstab;
  278.     }
  279.  
  280.     /* duplicate the current fstab */
  281.     newfstab.numEntries = fstab->numEntries;
  282.     newfstab.entries = malloc(fstab->numEntries * sizeof(struct fstabEntry));
  283.     for (i = j = 0; i < newfstab.numEntries; i++) {
  284.     if (fstab->entries[i].mntpoint) {
  285.         newfstab.entries[j] = fstab->entries[i];
  286.         newfstab.entries[j].mntpoint = nstrdup(fstab->entries[i].mntpoint);
  287.         newfstab.entries[j].device = nstrdup(fstab->entries[i].device);
  288.         newfstab.entries[j].netPath = nstrdup(fstab->entries[i].netPath);
  289.         newfstab.entries[j].netHost = nstrdup(fstab->entries[i].netHost);
  290.         j++;
  291.     }
  292.     }
  293.  
  294.     newfstab.numEntries = j;
  295.  
  296.     /* return the memory we don't actually need */
  297.     newfstab.entries = realloc(newfstab.entries, j * sizeof(struct fstabEntry));
  298.  
  299.     return newfstab;
  300. }
  301.  
  302. static int mkExt2Filesystem(char * dev) {
  303.     char * mke2fsargs[] = { "mke2fs", NULL, NULL, NULL};
  304.     int rc;
  305.     char message[80];
  306.  
  307.     mke2fsargs[1] = alloca(strlen(dev) + 6);
  308.     strcpy(mke2fsargs[1], "/tmp/");
  309.     strcat(mke2fsargs[1], dev);
  310.  
  311.     if (badBlocks)
  312.     mke2fsargs[2] = "-c";
  313.  
  314.     sprintf(message, _("Making ext2 filesystem on /dev/%s..."), dev);
  315.     winStatus(60, 3, _("Running"), message);
  316.  
  317.     devMakeInode(dev, mke2fsargs[1]);
  318.     rc = runProgram(RUN_LOG, "/usr/bin/mke2fs", mke2fsargs);
  319.     devRemoveInode(mke2fsargs[1]);
  320.  
  321.     newtPopWindow();
  322.  
  323.     if (rc)
  324.     return INST_ERROR;
  325.     else
  326.     return 0;
  327. }
  328.  
  329. int queryFormatFilesystems(struct fstab * fstab) {
  330.     newtComponent form, checkList, okay, cancel, sb, text, answer;
  331.     newtComponent checkbox, blank;
  332.     newtGrid grid, subgrid, checkgrid, buttons;
  333.     char * states;
  334.     char doCheck = ' ';
  335.     newtComponent * checks;
  336.     char buf[80];
  337.     int i, top;
  338.  
  339.     form = newtForm(NULL, NULL, 0);
  340.  
  341.     if (fstab->numEntries > 4) {
  342.     sb = newtVerticalScrollbar(47, 7, 4, 9, 10);
  343.     } else
  344.     sb = NULL;
  345.  
  346.     checkList = newtForm(sb, NULL, 0);
  347.     if (sb) newtFormSetHeight(checkList, 4);
  348.  
  349.     text = newtTextboxReflowed(-1, -1, _("What partitions would you like to "
  350.                "format? We strongly suggest formatting all of the "
  351.                "system partitions, including /, /usr, and /var. There "
  352.                "is no need to format /home or /usr/local if they "
  353.                "have already been configured during a previous "
  354.                "install."), 55, 0, 15, 0);
  355.  
  356.     checks = alloca(sizeof(newtComponent) * fstab->numEntries);
  357.     states = alloca(sizeof(char) * fstab->numEntries);
  358.     for (i = 0, top = 0; i < fstab->numEntries; i++) {
  359.     if (fstab->entries[i].doFormat)
  360.         states[i] = '*';
  361.     else
  362.         states[i] = ' ';
  363.  
  364.     if (fstab->entries[i].type == PART_EXT2) {
  365.         sprintf(buf, "/dev/%-5s  %-33s", fstab->entries[i].device, 
  366.            fstab->entries[i].mntpoint);
  367.         checks[i] = newtCheckbox(-1, top++, buf, states[i], NULL, 
  368.                      &states[i]);
  369.         newtFormAddComponent(checkList, checks[i]);
  370.     } else {
  371.         checks[i] = NULL;
  372.     }
  373.     }
  374.  
  375.     if (top > 4) {
  376.     blank = newtForm(NULL, NULL, 0);
  377.     newtFormSetWidth(blank, 2);
  378.     newtFormSetHeight(blank, 4);
  379.     newtFormSetBackground(blank, NEWT_COLORSET_CHECKBOX);
  380.     checkgrid = newtGridHCloseStacked(
  381.                 NEWT_GRID_COMPONENT, checkList,
  382.                 NEWT_GRID_COMPONENT, blank,
  383.                 NEWT_GRID_COMPONENT, sb, NULL);
  384.     } else {
  385.     checkgrid = newtGridHCloseStacked(NEWT_GRID_COMPONENT, checkList,
  386.                       NULL);
  387.     }
  388.  
  389.     checkbox = newtCheckbox(10, 12, _("Check for bad blocks during format"),
  390.                 badBlocks ? '*' : ' ', NULL, &doCheck);
  391.  
  392.     buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL);
  393.     subgrid = newtCreateGrid(1, 3);
  394.     subgrid = newtGridVStacked(NEWT_GRID_SUBGRID, checkgrid,
  395.                    NEWT_GRID_COMPONENT, checkbox, NULL);
  396.     grid = newtGridBasicWindow(text, subgrid, buttons);
  397.     newtGridAddComponentsToForm(grid, form, 1);
  398.     newtGridWrappedWindow(grid, _("Partitions To Format"));
  399.     newtGridFree(grid, 1);
  400.  
  401.     answer = newtRunForm(form);
  402.  
  403.     newtFormDestroy(form);
  404.     newtPopWindow();
  405.  
  406.     if (answer == cancel) return INST_CANCEL;
  407.  
  408.     for (i = 0; i < fstab->numEntries; i++) {
  409.     fstab->entries[i].doFormat = (states[i] != ' ');
  410.     }
  411.  
  412.     if (doCheck == ' ')
  413.     badBlocks = 0;
  414.     else
  415.     badBlocks = 1;
  416.  
  417.     return 0;
  418. }
  419.  
  420. int formatFilesystems(struct fstab * fstab) {
  421.     int i;
  422.  
  423.     for (i = 0; i < fstab->numEntries; i++) {
  424.         if (fstab->entries[i].doFormat)
  425.         mkExt2Filesystem(fstab->entries[i].device);
  426.     }
  427.  
  428.     return 0;
  429. }
  430.  
  431. int doMount(char * dev, char * where, char * fs, int rdonly, int istty) {
  432.     return doPwMount(dev, where, fs, rdonly, istty, NULL, NULL);
  433. }
  434.  
  435. int doPwMount(char * dev, char * where, char * fs, int rdonly, int istty,
  436.         char * acct, char * pw) { 
  437.     char * buf = NULL;
  438.     int isnfs = 0;
  439.     char * mount_opt = NULL;
  440.     long int flag;
  441.     char * chptr;
  442.  
  443.     if (!strcmp(fs, "nfs")) isnfs = 1;
  444.  
  445.     logMessage("mounting %s on %s as type %s", dev, where, fs);
  446.  
  447.     if (testing) {
  448.     newtWinMessage("Test mount", "Ok", "I would mount /dev/%s on %s",
  449.         "using a(n) %s filesystem.", dev, where, fs);
  450.     } else if (!strcmp(fs, "smb")) {
  451.     mkdirChain(where);
  452.  
  453.     if (!acct) acct = "guest";
  454.     if (!pw) pw = "";
  455.  
  456.     buf = alloca(strlen(dev) + 1);
  457.     strcpy(buf, dev);
  458.     chptr = buf;
  459.     while (*chptr && *chptr != ':') chptr++;
  460.     if (!*chptr) {
  461.         logMessage("bad smb mount point %s", where);
  462.         return 0;
  463.     } 
  464.     
  465.     *chptr = '\0';
  466.     chptr++;
  467.  
  468. #ifdef __i386__
  469.     logMessage("mounting smb filesystem from %s path %s on %s",
  470.             buf, chptr, where);
  471.     return smbmount(buf, chptr, acct, pw, "localhost", where);
  472. #else 
  473.     errorWindow("smbfs only works on Intel machines");
  474. #endif
  475.     } else {
  476.     mkdirChain(where);
  477.  
  478.       if (!isnfs && *dev == '/') {
  479.         buf = dev;
  480.     } else if (!isnfs) {
  481.         buf = alloca(200);
  482.         strcpy(buf, "/tmp/");
  483.         strcat(buf, dev);
  484.  
  485.         if (devMakeInode(dev, buf)) return 1;
  486.     } else {
  487.         char * junk = NULL;
  488.         int morejunk = 0;
  489.  
  490.         buf = dev;
  491.         logMessage("calling nfsmount(%s, %s, &morejunk, &junk, &mount_opt)",
  492.             buf, where);
  493.  
  494.         if (nfsmount(buf, where, &morejunk, &junk, &mount_opt))
  495.         logMessage("\tnfsmount returned non-zero");
  496.     }
  497.  
  498.     flag = MS_MGC_VAL;
  499.     if (rdonly)
  500.         flag |= MS_RDONLY;
  501.     
  502.     logMessage("calling mount(%s, %s, %s, %ld, %p)", buf, where, fs, 
  503.             flag, mount_opt);
  504.  
  505.     if (mount(buf, where, fs, flag, mount_opt)) {
  506.         if (istty) {
  507.         fprintf(stderr, "mount failed: %s\n", strerror(errno));
  508.         } else {
  509.         newtWinMessage(_("Error"), _("Ok"), 
  510.                 _("mount failed: %s"), strerror(errno));
  511.         }
  512.         return 1;
  513.     }
  514.  
  515.     if (!isnfs) devRemoveInode(buf);
  516.     }
  517.  
  518.     return 0;
  519. }
  520.  
  521. int mountFilesystems(struct fstab * fstab) {
  522.     int i;
  523.     char buf[1000];
  524.  
  525.     /* don't bother mounting odd (non-ext2) filesystems - we don't need
  526.        them for installs */
  527.  
  528.     /* what about NFS? we should probably mount them to check mount integrity,
  529.        but we don't know if networking is working well enough for us to do
  530.        this */
  531.    
  532.     chdir("/");
  533.  
  534.     for (i = 0; i < fstab->numEntries; i++) {
  535.     strcpy(buf, "/mnt");
  536.     strcat(buf, fstab->entries[i].mntpoint);
  537.  
  538.     if (fstab->entries[i].type == PART_EXT2 ||
  539.         fstab->entries[i].type == PART_NFS ) {
  540.         if (fstab->entries[i].type == PART_EXT2 &&
  541.         !doMount(fstab->entries[i].device, buf, "ext2", 0, 0))
  542.         fstab->entries[i].isMounted = 1;
  543.         else if (fstab->entries[i].type == PART_NFS &&
  544.         !doMount(fstab->entries[i].device, buf, "nfs", 0, 0))
  545.         fstab->entries[i].isMounted = 1;
  546.         else {
  547.         logMessage("unmounting all filesystems due to mount error");
  548.         umountFilesystems(fstab);
  549.         return INST_ERROR;
  550.         }
  551.     } else {
  552.         logMessage("creating directory %s", buf);
  553.         mkdirChain(buf);
  554.     }
  555.     }
  556.  
  557.     return 0;
  558. }
  559.  
  560. int umountFilesystems(struct fstab * fstab) {
  561.     char buf[1000];
  562.     int i;
  563.     int olderrno;
  564.  
  565.     logMessage("unmounting all filesystems");
  566.  
  567.     chdir("/");
  568.  
  569.     if (testing) return 0;
  570.  
  571.     for (i = fstab->numEntries - 1; i >= 0; i--) {
  572.     if (fstab->entries[i].isMounted) {
  573.         strcpy(buf, "/mnt");
  574.         strcat(buf, fstab->entries[i].mntpoint);
  575.  
  576.         fstab->entries[i].isMounted = 0;
  577.         if (umount(buf)) {
  578.         olderrno = errno;
  579.         logMessage("error unmounting %s: %s\n", buf, strerror(errno));
  580.         errno = olderrno;
  581.         errorWindow("error unmounting filesystem: %s");
  582.         }
  583.     }    
  584.     }
  585.  
  586.     return 0;
  587. }
  588.  
  589. static int mkdirChain(char * origChain) {
  590.     char * chain;
  591.     char * chptr;
  592.  
  593.     chain = alloca(strlen(origChain) + 1);
  594.     strcpy(chain, origChain);
  595.     chptr = chain;
  596.  
  597.     if (testing) return 0;
  598.  
  599.     while ((chptr = strchr(chptr, '/'))) {
  600.     *chptr = '\0';
  601.     if (mkdirIfNone(chain)) {
  602.         *chptr = '/';
  603.         return INST_ERROR;
  604.     }
  605.  
  606.     *chptr = '/';
  607.     chptr++;
  608.     }
  609.  
  610.     if (mkdirIfNone(chain))
  611.     return INST_ERROR;
  612.  
  613.     return 0;
  614. }
  615.  
  616. static int mkdirIfNone(char * directory) {
  617.     int rc, mkerr;
  618.     char * chptr;
  619.  
  620.     /* If the file exists it *better* be a directory -- I'm not going to
  621.        actually check or anything */
  622.     if (!access(directory, X_OK)) return 0;
  623.  
  624.     /* if the path is '/' we get ENOFILE not found" from mkdir, rather
  625.        then EEXIST which is weird */
  626.     for (chptr = directory; *chptr; chptr++)
  627.         if (*chptr != '/') break;
  628.     if (!*chptr) return 0;
  629.  
  630.     rc = mkdir(directory, 0755);
  631.     mkerr = errno;
  632.  
  633.     logMessage("creating directory %s rc = %d", directory, rc);
  634.  
  635.     if (!rc || mkerr == EEXIST) return 0;
  636.  
  637.     logMessage("    error: %s", strerror(mkerr));
  638.  
  639.     return INST_ERROR;
  640. }
  641.  
  642. int writeFstab(struct fstab * fstab) {
  643.     int i;
  644.     FILE * f;
  645.     int fd;
  646.     char * fs = NULL;
  647.     int freq = 0;
  648.     int passno = 0;
  649.     int bad;
  650.     char buf[4096];
  651.     char * chptr, * cddev = NULL;
  652.     char * devFormat = "/dev/%-18s %-23s %-7s %-15s %d %d\n";
  653.     char * nfsFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  654.     char * procFormat = "%-23s %-23s %-7s %-15s %d %d\n";
  655.     char * options;
  656.     char * format;
  657.  
  658.     logMessage("scanning /proc/mounts for iso9660 filesystems");
  659.     fd = open("/proc/mounts", O_RDONLY);
  660.     if (fd < 0) {
  661.     logMessage("\terror opening /proc/mounts -- skipping check: %s",
  662.             strerror(errno));
  663.     } else {
  664.     i = read(fd, buf, sizeof(buf) - 1);
  665.     if (i < 0) {
  666.         logMessage("\terror reading /proc/mounts -- skipping check: %s",
  667.                 strerror(errno));
  668.     } else {
  669.         buf[i] = 0;
  670.         if ((chptr = strstr(buf, "iso9660"))) {
  671.         chptr--;
  672.  
  673.         /* skip the mount point */
  674.         while (*chptr == ' ') chptr--;
  675.         while (*chptr != ' ') chptr--;
  676.         while (*chptr == ' ') chptr--;
  677.  
  678.         chptr++;
  679.         *chptr = '\0';
  680.         while (*chptr != '/') chptr--;
  681.         cddev = strdup(chptr + 1);
  682.         
  683.         logMessage("found mounted cdrom drive %s", cddev);
  684.         }
  685.     }
  686.     }
  687.  
  688.     #ifndef __sparc__
  689.     if (!cddev) {
  690.     if (findAtapi(&cddev)) cddev = NULL;
  691.     }
  692.     #endif
  693.  
  694.     /* cd-rom rooted installs have the cdrom mounted on /dev/root which */
  695.     /* is not what we want to symlink to /dev/cdrom.                    */
  696.  
  697.     if (!cddev || !strncmp(cddev, "root", 4)) {
  698.     if (findSCSIcdrom(&cddev)) cddev = NULL;
  699.     }
  700.  
  701.     if (testing) {
  702.     if (cddev) free(cddev);
  703.     return 0;
  704.     }
  705.  
  706.     logMessage("touching /etc/mtab");
  707.     f = fopen("/mnt/etc/mtab", "w+");
  708.     if (!f) {
  709.     errorWindow("error touching /mnt/etc/mtab");
  710.     } else {
  711.     fclose(f);
  712.     }
  713.  
  714.     logMessage("creating /etc/fstab");
  715.  
  716.     f = fopen("/mnt/etc/fstab", "w");
  717.     if (!f) {
  718.     if (cddev) free(cddev);
  719.     errorWindow("error creating /mnt/etc/fstab");
  720.     return INST_ERROR;
  721.     }
  722.  
  723.     for (i = 0; i < fstab->numEntries; i++) {
  724.     if (!fstab->entries[i].mntpoint) continue;
  725.  
  726.     passno = 0;
  727.     freq = 0;
  728.     format = devFormat;
  729.         options = "defaults";
  730.  
  731.     bad = 0;
  732.     switch (fstab->entries[i].type) {
  733.       case PART_EXT2:
  734.         freq = 1;
  735.         fs = "ext2";
  736.         if (!strcmp(fstab->entries[i].mntpoint, "/"))
  737.         passno = 1;
  738.         else
  739.         passno = 2;
  740.       
  741.         break;
  742.  
  743.       case PART_NFS:
  744.         fs = "nfs";
  745.         options = "ro";
  746.         format = nfsFormat;
  747.         break;
  748.  
  749.       case PART_SWAP:
  750.         fs = "swap";
  751.         break;
  752.  
  753.       case PART_DOS:
  754.         fs = "vfat";
  755.         break;
  756.  
  757.       case PART_HPFS:
  758.         fs = "hpfs";
  759.         break;
  760.  
  761.       default:
  762.         bad = 1;
  763.     }
  764.  
  765.     if (!bad)
  766.         fprintf(f, format, fstab->entries[i].device, 
  767.             fstab->entries[i].mntpoint, fs, options, freq, passno);
  768.     }
  769.  
  770.     fprintf(f, devFormat, "fd0", "/mnt/floppy", "ext2", "noauto", 0, 0);
  771.     if (cddev) {
  772.     if (mkdir("/mnt/mnt/cdrom", 0755)) 
  773.         logMessage("failed to mkdir /mnt/mnt/cdrom: %s", strerror(errno));
  774.  
  775.     if (symlink(cddev, "/mnt/dev/cdrom"))
  776.         logMessage("failed to symlink /mnt/dev/cdrom: %s", strerror(errno));
  777.  
  778.     fprintf(f, devFormat, "cdrom", "/mnt/cdrom", "iso9660", "noauto,ro", 
  779.         0, 0);
  780.     free(cddev);
  781.     }
  782.  
  783.     fprintf(f, procFormat, "none", "/proc", "proc", "defaults", 0, 0);
  784.  
  785.     fclose(f);
  786.  
  787.  
  788.     return 0;
  789. }
  790.  
  791. int addFstabEntry(struct fstab * fstab, struct fstabEntry entry) {
  792.     int i;
  793.  
  794.     for (i = 0; i < fstab->numEntries; i++) 
  795.     if (!strcmp(entry.device, fstab->entries[i].device))
  796.         break;
  797.  
  798.     if (i == fstab->numEntries) {
  799.     fstab->numEntries++;
  800.     if (fstab->numEntries > 1)
  801.         fstab->entries = realloc(fstab->entries, 
  802.                 sizeof(entry) * fstab->numEntries);
  803.     else
  804.         fstab->entries = malloc(sizeof(entry));
  805.     }
  806.  
  807.     fstab->entries[i] = entry;
  808.  
  809.     return i;
  810. }
  811.