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

  1. #include <ctype.h>
  2. #include <fcntl.h>
  3. #include <linux/hdreg.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/stat.h>
  9. #include <sys/sysmacros.h>
  10. #include <sys/wait.h>
  11. #include <unistd.h>
  12.  
  13. #include "hd.h"
  14. #include "install.h"
  15. #include "intl.h"
  16. #include "libfdisk/libfdisk.h"
  17. #include "log.h"
  18. #include "newt.h"
  19. #include "run.h"
  20. #include "scsi.h"
  21. #include "windows.h"
  22.  
  23. #define MAX_HARDDRIVES 16
  24.  
  25. extern int testing;
  26.  
  27. /* shame we can't get this from any header files */
  28. #define BLKRRPART  _IO(0x12,95)    /* re-read partition table */
  29.  
  30. struct fdiskTag {
  31.     int tag;
  32.     int type;
  33.     char * tagName;
  34. } ;
  35.  
  36. #if defined(__sparc__)
  37. const struct fdiskTag fdiskTags[] =  {
  38.     { 0x05,    PART_IGNORE, N_("Whole disk") },
  39.     { 0x82,    PART_SWAP, N_("Linux swap") },
  40.     { 0x83,    PART_EXT2, N_("Linux native") },
  41.     { 0, 0 },
  42. };
  43. #else
  44. const struct fdiskTag fdiskTags[] =  {
  45.     { 0x01,    PART_DOS, N_("DOS 12-bit FAT") },
  46.     { 0x04,    PART_DOS, N_("DOS 16-bit <32M") },
  47.     { 0x05,    PART_IGNORE, "Extended" },
  48.     { 0x06,    PART_DOS, N_("DOS 16-bit >=32") },
  49.     { 0x07,    PART_HPFS, N_("OS/2 HPFS") },
  50.     { 0x0b,    PART_FAT32, N_("Win95 FAT32") },
  51.     { 0x0c,    PART_FAT32, N_("Win95 FAT32") },
  52.     { 0x0e,    PART_FAT32, N_("Win95 FAT32") },
  53.     { 0x82,    PART_SWAP, N_("Linux swap") },
  54.     { 0x83,    PART_EXT2, N_("Linux native") },
  55.     { 0, 0 },
  56. };
  57. #endif
  58.  
  59. #define MAX_NUM_DRIVES 40
  60.  
  61. static int findDrivesPresent(struct deviceInfo * drives, int * numPtr);
  62.  
  63. static int findPartitions(char * hdname, int * numPartitions, 
  64.               struct partition partitions[15]) {
  65.     char devBuf[20];
  66.     int j, i;
  67.     int status;
  68.     HardDrive * hd = NULL;
  69.     PartitionSpec spec;
  70.  
  71.     *numPartitions = 0;
  72.  
  73.     /* don't bother with any of this if the main device doesn't exist 
  74.        or doesn't look like a hard drive */
  75.     sprintf(devBuf, "/tmp/%s", hdname);
  76.     
  77.     if (devMakeInode(hdname, devBuf)) {
  78.     return 0;
  79.     }
  80.  
  81.     status = fdiskOpenDevice(devBuf, 0, &hd);
  82.     if (status != FDISK_SUCCESS) {
  83.     unlink(devBuf);
  84.     return 0;
  85.     }
  86.  
  87.     status = fdiskReadPartitions(hd);
  88.     if (status != FDISK_SUCCESS) {
  89.     fdiskCloseDevice(hd);
  90.     unlink(devBuf);
  91.     return 0;
  92.     }
  93.  
  94.     fdiskCloseDevice(hd);
  95.     unlink(devBuf);
  96.  
  97.     /* Translate into a PartitionSpec */
  98.     memset(&spec, 0, sizeof(PartitionSpec));
  99.     fdiskSetupPartitionSpec(&hd, 1, &spec );
  100.  
  101.     *numPartitions = spec.num;
  102.     for (i = 0; i < spec.num; i++) {
  103.     memset(partitions + i, 0, sizeof(*partitions));
  104.     sprintf(partitions[i].device, "%s%d",
  105.         hdname, spec.entry[i].partition.num.current);
  106.     /* the /2 converts from 512 byte sectors to 1k blocks */
  107.     partitions[i].size = spec.entry[i].partition.size.current / 2;
  108.     partitions[i].begin = spec.entry[i].partition.start.current;
  109.     partitions[i].end = spec.entry[i].partition.endcyl.current;
  110.  
  111.     for (j = 0; fdiskTags[j].tag; j++) {
  112.         if (fdiskTags[j].tag == spec.entry[i].partition.type.current) {
  113.         partitions[i].type = fdiskTags[j].type;
  114.         strcpy(partitions[i].tagName, fdiskTags[j].tagName);
  115.         break;
  116.         }
  117.     }
  118.  
  119.     }
  120.  
  121.     return 0;
  122. }
  123.  
  124. int findAllPartitions(struct deviceInfo * devices, 
  125.              struct partitionTable * table) {
  126.     int numPartitions;
  127.     int i;
  128.     struct partition parts[16];
  129.     struct partition * allParts = NULL;
  130.     int numAllParts = 0;
  131.  
  132.     if (!devices) {
  133.     /* FIXME: memory leak for internal structures */
  134.     devices = alloca(sizeof(*devices) * MAX_NUM_DRIVES);
  135.     if (findDrivesPresent(devices, NULL)) return INST_ERROR;
  136.     }
  137.  
  138.     winStatus(30, 3, _("Hard Drives"), _("Scanning hard drives..."));
  139.  
  140.     for (i = 0; devices[i].deviceName; i++) {
  141.     findPartitions(devices[i].deviceName, &numPartitions, parts);
  142.     if (!numPartitions) continue;
  143.     
  144.     if (!numAllParts) {
  145.         numAllParts = numPartitions;
  146.         allParts = malloc(sizeof(*allParts) * numAllParts);
  147.         memcpy(allParts, parts, sizeof(*allParts) * numAllParts);
  148.     } else {
  149.         allParts = realloc(allParts, sizeof(*allParts) * 
  150.                 (numAllParts + numPartitions));
  151.         memcpy(allParts + numAllParts, parts, 
  152.            sizeof(*allParts) * numPartitions);
  153.         numAllParts += numPartitions;
  154.     }
  155.     }
  156.  
  157.     table->count = numAllParts;
  158.     table->parts = allParts;
  159.  
  160.     newtPopWindow();
  161.  
  162.     return 0;
  163. }
  164.  
  165. static int findDrivesPresent(struct deviceInfo * drives, int * numPtr) {
  166.     struct deviceInfo * scsi = NULL, * ide = NULL;
  167.     int num = 0; 
  168.     int i;
  169.  
  170.     /* FIXME: this results in memory leaks via the strings inside of
  171.        the decice structures! */
  172.  
  173.     if (scsiDeviceAvailable()) {
  174.     if (scsiGetDevices(&scsi)) return INST_ERROR;
  175.     }
  176.  
  177.     if (ideGetDevices(&ide)) return INST_ERROR;
  178.  
  179.     i = 0, num = 0;
  180.     while (ide[i].deviceName) {
  181.     if (ide[i].type == DEVICE_HD) 
  182.         drives[num++] = ide[i];
  183.     i++;
  184.     }
  185.  
  186.     i = 0;
  187.     while (scsi && scsi[i].deviceName) {
  188.     if (scsi[i].type == DEVICE_HD) 
  189.         drives[num++] = scsi[i];
  190.     i++;
  191.     }
  192.  
  193.     drives[num].deviceName = NULL;
  194.  
  195.     if (numPtr) *numPtr = num;
  196.  
  197.     return 0;
  198. }
  199.  
  200. int getDriveList(char *** drives, int * num) {
  201.     struct deviceInfo drivesPresent[MAX_NUM_DRIVES];
  202.     int rc;
  203.     int i;
  204.  
  205.     if ((rc = findDrivesPresent(drivesPresent, num))) return rc;
  206.  
  207.     *drives = malloc(sizeof(char *) * (*num + 1));
  208.  
  209.     for (i = 0; i < *num; i++) {
  210.     (*drives)[i] = drivesPresent[i].deviceName;
  211.     }
  212.  
  213.     (*drives)[i] = NULL;
  214.  
  215.     return 0;
  216. }
  217.     
  218. int partitionDrives(void) {
  219.     struct deviceInfo drivesPresent[MAX_NUM_DRIVES];
  220.     int numDrivesPresent = 0;
  221.     int childpid;
  222.     int i, fd;
  223.     int haveEdited = 0;
  224.     char devBuf[100], idBuf[3];
  225.     char * driveText[50];
  226.     struct deviceInfo * currhd;
  227.     int status;
  228.     int reboot = 0;
  229.     char * cmd;
  230.     char * text;
  231.     int rc, driveNum = 0;
  232.  
  233.     if (!access("/sbin/fdisk", X_OK))
  234.     cmd = "/sbin/fdisk";
  235.     else
  236.     cmd = "/usr/bin/fdisk";
  237.  
  238.     findDrivesPresent(drivesPresent, &numDrivesPresent);
  239.  
  240.     if (!numDrivesPresent) {
  241.     newtWinMessage(_("Hard Drives"), _("Ok"), 
  242.                _("You don't have any hard drives available! "
  243.                  "You probably forgot to configure a SCSI "
  244.                  "controller."));
  245.  
  246.     return INST_ERROR;
  247.     }
  248.  
  249. #ifdef __i386__
  250.     text = _("To install Red Hat Linux, you must have at least one parition "
  251.          "of 150 MB dedicated to Linux. We suggest placing that partition "
  252.          "on one of the first two hard drives in your system so you can "
  253.          "boot into Linux with LILO.");
  254. #else
  255.     text = _("To install Red Hat Linux, you must have at least one parition "
  256.          "of 150 MB dedicated to Linux.");
  257. #endif
  258.  
  259.     for (i = 0; i < numDrivesPresent; i++) {
  260.     sprintf(devBuf, "/dev/%s", drivesPresent[i].deviceName);
  261.  
  262.     if (!strncmp(drivesPresent[i].deviceName, "sd", 2)) {
  263.         sprintf(idBuf, "%d", drivesPresent[i].id);
  264.         strcat(devBuf, " - SCSI ID ");
  265.         strcat(devBuf, idBuf);
  266.     } 
  267.  
  268.     strcat(devBuf, " - Model ");
  269.     strcat(devBuf, drivesPresent[i].info);
  270.  
  271.     /* truncate at 50 columns for now */
  272.     devBuf[50] = '\0';
  273.  
  274.         driveText[i] = alloca(strlen(devBuf) + 1);
  275.         strcpy(driveText[i], devBuf);
  276.     }
  277.     driveText[i] = NULL;
  278.  
  279.     do {
  280.     rc = newtWinMenu(_("Partition Disks"), text, 56, 5, 6, 5,
  281.              driveText, &driveNum, _("Done"), _("Edit"),
  282.              _("Back"), NULL);
  283.  
  284.     if (rc == 2 || rc == 0) {
  285.         haveEdited = 1;
  286.         currhd = drivesPresent + driveNum;
  287.  
  288.         sprintf(devBuf, "/tmp/%s", currhd->deviceName);
  289.         if (devMakeInode(currhd->deviceName, devBuf)) return 0;
  290.  
  291.         newtSuspend();
  292.         for (i = 0; i < 25; i++) puts("");
  293.         printf("This is the fdisk program for partitioning your drive. It "
  294.            "is running\non /dev/%s.\n\n", currhd->deviceName);
  295.  
  296.         logMessage("running fdisk on %s", devBuf);
  297.         
  298.         if (!(childpid = fork())) {
  299.         execl(cmd, cmd, devBuf, NULL);
  300.          return -1;
  301.         }
  302.  
  303.         waitpid(childpid, &status, 0);
  304.  
  305.         newtResume();
  306.     }
  307.     } while (rc == 2 || rc == 0);
  308.  
  309.     if (haveEdited) {
  310.     for (i = 0; i < numDrivesPresent; i++) {
  311.         sprintf(devBuf, "/tmp/%s", drivesPresent[i].deviceName);
  312.         if (devMakeInode(drivesPresent[i].deviceName, devBuf)) 
  313.         return INST_ERROR;
  314.         fd = open(devBuf, O_RDONLY);
  315.         unlink(devBuf);
  316.         if (fd < 0) reboot = 1;
  317.  
  318.         if (ioctl(fd, BLKRRPART, 0)) reboot = 1;
  319.         close(fd);
  320.     }
  321.     }
  322.  
  323.     if (reboot) needReboot();
  324.  
  325.     if (rc == 3)
  326.     return INST_CANCEL;
  327.  
  328.     return 0;
  329. }
  330.  
  331. void needReboot(void) {
  332.     newtWinMessage(_("Reboot Needed"), _("Ok"),
  333.             _("The kernel is unable to read your new partitioning "
  334.             "information, probably because you modified extended "
  335.             "partitions. While this is not critical, you must "
  336.             "reboot your machine before proceeding. Insert the "
  337.             "Red Hat boot disk now and press Return to reboot "
  338.             "your system.\n\n"
  339.             "If you have a ZIP or JAZ drive, make sure there is "
  340.             "a disk in the drive as an empty SCSI drive can also "
  341.             "cause this problem."));
  342.  
  343.     newtFinished();
  344.     exit(0);
  345. }
  346.