home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / HD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  12.2 KB  |  482 lines

  1. #include <ctype.h>
  2. #include <fcntl.h>
  3. #include <linux/hdreg.h>
  4. #include <linux/fs.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/ioctl.h>
  9. #include <sys/stat.h>
  10. #include <sys/sysmacros.h>
  11. #include <sys/wait.h>
  12. #include <unistd.h>
  13.  
  14. #include "hd.h"
  15. #include "install.h"
  16. #include "log.h"
  17. #include "newt.h"
  18. #include "run.h"
  19. #include "windows.h"
  20.  
  21. extern int testing;
  22.  
  23. struct fdiskTag {
  24.     int tag;
  25.     int type;
  26. } ;
  27.  
  28. #if defined(__sparc__)
  29. const struct fdiskTag fdiskTags[] =  {
  30.     { 0x05,    PART_IGNORE },
  31.     { 0x82,    PART_SWAP },
  32.     { 0x83,    PART_EXT2 },
  33.     { 0, 0 },
  34. };
  35. #else
  36. const struct fdiskTag fdiskTags[] =  {
  37.     { 0x01,    PART_DOS },
  38.     { 0x04,    PART_DOS },
  39.     { 0x05,    PART_IGNORE },
  40.     { 0x06,    PART_DOS },
  41.     { 0x07,    PART_HPFS },
  42.     { 0x82,    PART_SWAP },
  43.     { 0x83,    PART_EXT2 },
  44.     { 0, 0 },
  45. };
  46. #endif
  47.  
  48. struct hd {
  49.     char * device;
  50.     int major, minor;
  51. };
  52.  
  53. struct hd static possibleDrives[] = {
  54. #ifndef __sparc__
  55.     { "hda",    3,    0 },
  56.     { "hdb",    3,    64 },
  57.     { "hdc",    22,    0 },
  58.     { "hdd",    22,    64 },
  59.     { "hde",    33,    0 },
  60.     { "hdf",    33,    64 },
  61.     { "hdg",    34,    0 },
  62.     { "hdh",    34,    64 },
  63. #endif
  64.     { "sda",    8,    0 },
  65.     { "sdb",    8,    16 },
  66.     { "sdc",    8,    32 },
  67.     { "sdd",    8,    48 },
  68.     { "sde",    8,    64 },
  69.     { "sdf",    8,    80 },
  70.     { "sdg",    8,    96 },
  71.     { "sdh",    8,    112 },
  72.  
  73. }; 
  74.  
  75. static void parseLabelLine(char * device, char * start, int * numPartitions, 
  76.                struct partition partitions[15]) {
  77.     char * str = start;
  78.     char * chptr;
  79.     char devbuf[2];
  80.  
  81.     if (*str++ != ' ') return;
  82.     if (*str++ != ' ') return;
  83.  
  84.     if (*str < 'a' || *str > 'h') return;
  85.     if (*(str + 1) != ':') return;
  86.  
  87.     strcpy(partitions[*numPartitions].device, device);
  88.     devbuf[0] = *str - 'a' + '1';
  89.     devbuf[1] = '\0';
  90.     strcat(partitions[*numPartitions].device, devbuf);
  91.     str += 2;
  92.  
  93.     while (*str && isspace(*str)) str++;
  94.     if (!*str) return;
  95.  
  96.     partitions[*numPartitions].size = strtol(str, &chptr, 10);
  97.     partitions[*numPartitions].size /= 2;    /* we want 1k blocks */
  98.     if (!chptr || !isspace(*chptr)) return;
  99.     str = chptr;
  100.  
  101.     while (isspace(*str)) str++;
  102.     if (!*str) return;
  103.  
  104.     partitions[*numPartitions].begin = strtol(str, &chptr, 10);
  105.     if (!chptr || !isspace(*chptr)) return;
  106.     str = chptr;
  107.  
  108.     partitions[*numPartitions].end = partitions[*numPartitions].size * 2 +
  109.                     partitions[*numPartitions].begin;
  110.  
  111.     while (isspace(*str)) str++;
  112.     if (!*str) return;
  113.  
  114.     if (!strncmp(str, "ext2", 4)) {
  115.     partitions[*numPartitions].type = PART_EXT2;
  116.     strcpy(partitions[*numPartitions].tagName, "Linux native");
  117.     } else if (!strncmp(str, "swap", 4)) {
  118.     partitions[*numPartitions].type = PART_SWAP;
  119.     strcpy(partitions[*numPartitions].tagName, "Linux swap");
  120.     } else {
  121.     partitions[*numPartitions].type = PART_OTHER;
  122.     strcpy(partitions[*numPartitions].tagName, "Other");
  123.     }
  124.     
  125.     partitions[*numPartitions].bootLabel = NULL;
  126.  
  127.     logMessage("found partition %s", partitions[*numPartitions].device);
  128.  
  129.     (*numPartitions)++;
  130. }
  131.  
  132. static void parseFdiskLine(char * device, char * start, int * numPartitions, 
  133.                struct partition partitions[15]) {
  134.     int tag, i;
  135.     char * str = start;
  136.     char * chptr;
  137.  
  138.     if (*str != '/') return;
  139.  
  140.     if (strlen(str) < 60) return;
  141.  
  142.     /* grab the partition number */
  143.     str += 8;
  144.     chptr = str;
  145.     
  146.     if (!isdigit(*chptr)) return;
  147.     while (*chptr && isdigit(*chptr)) chptr++;
  148.     if (!*chptr) return;
  149.  
  150.     *chptr = '\0';
  151.     strcpy(partitions[*numPartitions].device, device);
  152.     strcat(partitions[*numPartitions].device, str);
  153.     str = chptr + 1;
  154.  
  155.     /* go to the "Begin" field, skipping the '*' which marks a bootable
  156.        partition and the 'u|r' fields which can occur on a Sun disklabel */
  157.     while (*str && (isspace(*str) || *str == '*' || *str == 'u' ||
  158.         *str == 'r')) str++;
  159.     if (!*str) return;
  160.  
  161.     /* skip the Begin: field (but make sure it's a number */
  162.     if (!isdigit(*str)) return;
  163.     while (isdigit(*str)) str++;
  164.     if (!*str || !isspace(*str)) return;
  165.  
  166.     /* go to the first digit in the "Start" field */
  167.     while (isspace(*str)) str++;
  168.     if (!*str) return;
  169.  
  170.     partitions[*numPartitions].begin = strtol(str, &chptr, 10);
  171.     if (!chptr || !isspace(*chptr)) return;
  172.     str = chptr;
  173.  
  174.     /* go to the first digit in the "End" field */
  175.     while (isspace(*str)) str++;
  176.     if (!*str) return;
  177.  
  178.     partitions[*numPartitions].end = strtol(str, &chptr, 10);
  179.     if (!chptr || !isspace(*chptr)) return;
  180.     str = chptr;
  181.  
  182.     /* go to the first digit in the "Size" field */
  183.     while (isspace(*str)) str++;
  184.     if (!*str) return;
  185.  
  186.     partitions[*numPartitions].size = strtol(str, &chptr, 10);
  187.     if (!chptr || (*chptr != '-' && *chptr != '+' && !isspace(*chptr)))
  188.     return;
  189.  
  190.     str = chptr + 1;
  191.  
  192.     /* go to the first digit in the "Tag" field */
  193.     while (isspace(*str)) str++;
  194.     if (!*str) return;
  195.     tag = strtol(str, &chptr, 16);
  196.  
  197.     partitions[*numPartitions].type = PART_OTHER;
  198.     for (i = 0; fdiskTags[i].tag; i++) {
  199.     if (fdiskTags[i].tag == tag) {
  200.         partitions[*numPartitions].type = fdiskTags[i].type;
  201.         break;
  202.     }
  203.     }
  204.     
  205.     str = chptr;
  206.     while (isspace(*str)) str++;
  207.     if (!*str) return;
  208.  
  209.     strcpy(partitions[*numPartitions].tagName, str);
  210.     partitions[*numPartitions].bootLabel = NULL;
  211.  
  212.     logMessage("found partition %s", partitions[*numPartitions].device);
  213.  
  214.     (*numPartitions)++;
  215. }
  216.  
  217. static int findPartitions(struct hd hd, int * numPartitions, 
  218.               struct partition partitions[15]) {
  219.     char devBuf[20];
  220.     int fd;
  221.     char * fdiskOutput;
  222.     char * fdiskArgs[] = { NULL, NULL, NULL };
  223.     char * start, * end;
  224.     int oldTesting;
  225.     int len;
  226.     char * cmd;
  227.     int labelMode = 0;
  228.     #if defined(__alpha__)
  229.     unsigned short magic;
  230.     unsigned int fdiskMagic = 0xAA55;
  231.     #endif
  232.  
  233.     if (testing)
  234.     cmd = "/sbin/fdisk";
  235.     else
  236.     cmd = "/usr/bin/fdisk";
  237.  
  238.     fdiskArgs[0] = cmd;
  239.  
  240.     *numPartitions = 0;
  241.  
  242.     /* don't bother with any of this if the main device doesn't exist */
  243.     sprintf(devBuf, "/tmp/%s", hd.device);
  244.     mknod(devBuf, S_IFBLK | 0600, makedev(hd.major, hd.minor));
  245.     fd = open(devBuf, O_RDONLY);
  246.     if (fd < 0) {
  247.     unlink(devBuf);
  248.     return 0;
  249.     }
  250.  
  251.     #if defined(__alpha__)
  252.     /* is this a labeled disk? */
  253.     /* This test used to just look for the disklabel magic, but that 
  254.        got left around on fdisks drives much of the time. This check
  255.        seems more reliable */
  256.     lseek(fd, 510, SEEK_SET);
  257.     if (read(fd, &magic, sizeof(magic)) == sizeof(magic))
  258.         labelMode = (magic != fdiskMagic);
  259.  
  260.     if (labelMode) 
  261.         logMessage("/dev/%s is disklabeled", hd.device);
  262.     else
  263.         logMessage("/dev/%s is fdisked", hd.device);
  264.     #endif
  265.  
  266.     close(fd);
  267.  
  268.     oldTesting = testing;
  269.     testing = 0;
  270.     fdiskArgs[1] = devBuf;
  271.     if (labelMode)
  272.     runProgramIO(RUN_NOLOG, cmd, fdiskArgs, "b\np\nq\n", &fdiskOutput);
  273.     else
  274.     runProgramIO(RUN_NOLOG, cmd, fdiskArgs, "p\nq\n", &fdiskOutput);
  275.     unlink(devBuf);
  276.     testing = oldTesting;
  277.  
  278.     start = fdiskOutput;
  279.     len = strlen(start);
  280.     while (((start - fdiskOutput) < len) && (end = strchr(start, '\n'))) {
  281.     *end = '\0';
  282.     if (labelMode)
  283.         parseLabelLine(hd.device, start, numPartitions, partitions);
  284.     else
  285.         parseFdiskLine(hd.device, start, numPartitions, partitions);
  286.     
  287.     start = end + 1;
  288.     }
  289.     free(fdiskOutput);
  290.  
  291.     return 0;
  292. }
  293.  
  294. int findAllPartitions(struct partitionTable * table) {
  295.     int numPartitions;
  296.     int i;
  297.     struct partition parts[16];
  298.     struct partition * allParts = NULL;
  299.     int numAllParts = 0;
  300.  
  301.     winStatus(30, 3, "Hard Drives", "Scanning hard drives...");
  302.  
  303.     for (i = 0; i < (sizeof(possibleDrives) / sizeof(*possibleDrives)); i++) {
  304.     findPartitions(possibleDrives[i], &numPartitions, parts);
  305.     if (!numPartitions) continue;
  306.     
  307.     if (!numAllParts) {
  308.         numAllParts = numPartitions;
  309.         allParts = malloc(sizeof(*allParts) * numAllParts);
  310.         memcpy(allParts, parts, sizeof(*allParts) * numAllParts);
  311.     } else {
  312.         allParts = realloc(allParts, sizeof(*allParts) * 
  313.                 (numAllParts + numPartitions));
  314.         memcpy(allParts + numAllParts, parts, 
  315.            sizeof(*allParts) * numPartitions);
  316.         numAllParts += numPartitions;
  317.     }
  318.     }
  319.  
  320.     table->count = numAllParts;
  321.     table->parts = allParts;
  322.  
  323.     newtPopWindow();
  324.  
  325.     return 0;
  326. }
  327.  
  328. int partitionDrives(void) {
  329.     int drivesPresent[sizeof(possibleDrives) / sizeof(*possibleDrives)];
  330.     int numDrivesPresent = 0;
  331.     int childpid;
  332.     int i, fd;
  333.     int haveEdited = 0;
  334.     char devBuf[20];
  335.     newtComponent cancel, done, edit, text, listbox, f, answer, okay, form;
  336.     struct hd_geometry geo;
  337.     struct hd * currhd;
  338.     char * cmd;
  339.     int status;
  340.     int reboot = 0;
  341.  
  342.     if (testing)
  343.     cmd = "/sbin/fdisk";
  344.     else
  345.     cmd = "/usr/bin/fdisk";
  346.  
  347.     for (i = 0; i < sizeof(possibleDrives) / sizeof(*possibleDrives); i++) {
  348.     sprintf(devBuf, "/tmp/%s", possibleDrives[i].device);
  349.     mknod(devBuf, S_IFBLK | 0600, 
  350.             makedev(possibleDrives[i].major, possibleDrives[i].minor));
  351.     fd = open(devBuf, O_RDONLY);
  352.     unlink(devBuf);
  353.     if (fd < 0) {
  354.         continue;
  355.     }
  356.  
  357.     logMessage("successfully opened: %s", devBuf);
  358.  
  359.     if (possibleDrives[i].device[0] == 'h') {
  360.         /* make sure this isn't an IDE CD or tape drive */
  361.         if (ioctl(fd, HDIO_GETGEO, &geo)) {
  362.         logMessage("\tHDIO_GETGEO ioctl failed - probably cd or tape");
  363.         close(fd);
  364.         continue;
  365.         }
  366.     }
  367.  
  368.     close(fd);
  369.  
  370.     drivesPresent[numDrivesPresent++] = i;
  371.     }
  372.  
  373.     if (!numDrivesPresent) {
  374.     newtOpenWindow(18, 6, 44, 11, "Setup Swap");
  375.     text = newtTextbox(1, 1, 42, 4, NEWT_TEXTBOX_WRAP);
  376.     newtTextboxSetText(text, "You don't have any hard drives available! "
  377.                  "You probably forgot to configure a SCSI "
  378.                  "controller.");
  379.     
  380.     okay = newtButton(17, 7, "Ok");
  381.  
  382.     form = newtForm(NULL, NULL, 0);
  383.     newtFormAddComponents(form, text, okay, NULL);
  384.     
  385.     newtRunForm(form);
  386.     newtFormDestroy(form);
  387.     newtPopWindow();
  388.  
  389.     return INST_ERROR;
  390.     }
  391.  
  392.     newtOpenWindow(10, 3, 60, 17, "Partition Disks");
  393.     text = newtTextbox(1, 1, 56, 5, NEWT_TEXTBOX_WRAP);
  394.     newtTextboxSetText(text, 
  395.             "To install Red Hat Linux, you must have at least "
  396.             "one parition of 50 MB dedicated to Linux. We suggest "
  397.             "placing that partition on one of the first two hard "
  398.             "drives in your system so you can boot into Linux "
  399.             "with LILO.");
  400.     
  401.     listbox = newtListbox(23, 7, 5, NEWT_LISTBOX_RETURNEXIT);
  402.     
  403.     for (i = 0; i < numDrivesPresent; i++) {
  404.     sprintf(devBuf, "/dev/%s", possibleDrives[drivesPresent[i]].device);
  405.     newtListboxAddEntry(listbox, devBuf, possibleDrives + drivesPresent[i]);
  406.     }
  407.  
  408.     done = newtButton(7, 13, "Done");
  409.     edit = newtButton(24, 13, "Edit");
  410.     cancel = newtButton(41, 13, "Cancel");
  411.  
  412.     f = newtForm(NULL, NULL, 0);
  413.     newtFormAddComponents(f, text, listbox, done, edit, cancel, NULL);
  414.     newtFormSetCurrent(f, done);
  415.   
  416.     do {
  417.     answer = newtRunForm(f);
  418.     
  419.     if (answer == edit || answer == listbox) {
  420.         haveEdited = 1;
  421.         currhd = newtListboxGetCurrent(listbox);
  422.  
  423.         sprintf(devBuf, "/tmp/%s", currhd->device);
  424.         mknod(devBuf, S_IFBLK | 0600, 
  425.             makedev(currhd->major, currhd->minor));
  426.  
  427.         newtPopWindow();
  428.         newtSuspend();
  429.         for (i = 0; i < 25; i++) puts("");
  430.         printf("This is the fdisk program for partitioning your drive. It "
  431.            "is running\non /dev/%s.\n\n", currhd->device);
  432.  
  433.         logMessage("running fdisk on %s", devBuf);
  434.         
  435.         if (!(childpid = fork())) {
  436.         execl(cmd, cmd, devBuf, NULL);
  437.          return -1;
  438.         }
  439.  
  440.         waitpid(childpid, &status, 0);
  441.  
  442.         newtResume();
  443.         newtOpenWindow(10, 3, 60, 17, "Partition Disks");
  444.     }
  445.     } while (answer != done && answer != cancel && answer != f);
  446.  
  447.     newtFormDestroy(f);
  448.     newtPopWindow();
  449.  
  450.     if (haveEdited) {
  451.     for (i = 0; i < numDrivesPresent; i++) {
  452.         sprintf(devBuf, "/tmp/%s", possibleDrives[drivesPresent[i]].device);
  453.         mknod(devBuf, S_IFBLK | 0600, 
  454.             makedev(possibleDrives[drivesPresent[i]].major, 
  455.                 possibleDrives[drivesPresent[i]].minor)); 
  456.         fd = open(devBuf, O_RDONLY);
  457.         unlink(devBuf);
  458.         if (fd < 0) reboot = 1;
  459.  
  460.         if (ioctl(fd, BLKRRPART, 0)) reboot = 1;
  461.         close(fd);
  462.     }
  463.     }
  464.  
  465.     if (reboot) {
  466.     winMessage(14, 6, 52, 12, "Reboot Needed",
  467.             "The kernel is unable to read your new partitioning "
  468.             "information, probably because you modified extended "
  469.             "partitions. While this is not critical, you must "
  470.             "reboot your machine before proceeding. Insert the "
  471.             "Red Hat boot disk now and press Return to reboot "
  472.             "your system.");
  473.     newtFinished();
  474.     exit(0);
  475.     }
  476.  
  477.     if (answer == cancel)
  478.     return INST_CANCEL;
  479.  
  480.     return 0;
  481. }
  482.