#include #include #include #include #include #include #include #include #include #include #include #include "hd.h" #include "install.h" #include "intl.h" #include "libfdisk/libfdisk.h" #include "log.h" #include "newt.h" #include "run.h" #include "scsi.h" #include "windows.h" #define MAX_HARDDRIVES 16 extern int testing; /* shame we can't get this from any header files */ #define BLKRRPART _IO(0x12,95) /* re-read partition table */ struct fdiskTag { int tag; int type; char * tagName; } ; #if defined(__sparc__) const struct fdiskTag fdiskTags[] = { { 0x05, PART_IGNORE, N_("Whole disk") }, { 0x82, PART_SWAP, N_("Linux swap") }, { 0x83, PART_EXT2, N_("Linux native") }, { 0, 0 }, }; #else const struct fdiskTag fdiskTags[] = { { 0x01, PART_DOS, N_("DOS 12-bit FAT") }, { 0x04, PART_DOS, N_("DOS 16-bit <32M") }, { 0x05, PART_IGNORE, "Extended" }, { 0x06, PART_DOS, N_("DOS 16-bit >=32") }, { 0x07, PART_HPFS, N_("OS/2 HPFS") }, { 0x0b, PART_FAT32, N_("Win95 FAT32") }, { 0x0c, PART_FAT32, N_("Win95 FAT32") }, { 0x0e, PART_FAT32, N_("Win95 FAT32") }, { 0x82, PART_SWAP, N_("Linux swap") }, { 0x83, PART_EXT2, N_("Linux native") }, { 0, 0 }, }; #endif #define MAX_NUM_DRIVES 40 static int findDrivesPresent(struct deviceInfo * drives, int * numPtr); static int findPartitions(char * hdname, int * numPartitions, struct partition partitions[15]) { char devBuf[20]; int j, i; int status; HardDrive * hd = NULL; PartitionSpec spec; *numPartitions = 0; /* don't bother with any of this if the main device doesn't exist or doesn't look like a hard drive */ sprintf(devBuf, "/tmp/%s", hdname); if (devMakeInode(hdname, devBuf)) { return 0; } status = fdiskOpenDevice(devBuf, 0, &hd); if (status != FDISK_SUCCESS) { unlink(devBuf); return 0; } status = fdiskReadPartitions(hd); if (status != FDISK_SUCCESS) { fdiskCloseDevice(hd); unlink(devBuf); return 0; } fdiskCloseDevice(hd); unlink(devBuf); /* Translate into a PartitionSpec */ memset(&spec, 0, sizeof(PartitionSpec)); fdiskSetupPartitionSpec(&hd, 1, &spec ); *numPartitions = spec.num; for (i = 0; i < spec.num; i++) { memset(partitions + i, 0, sizeof(*partitions)); sprintf(partitions[i].device, "%s%d", hdname, spec.entry[i].partition.num.current); /* the /2 converts from 512 byte sectors to 1k blocks */ partitions[i].size = spec.entry[i].partition.size.current / 2; partitions[i].begin = spec.entry[i].partition.start.current; partitions[i].end = spec.entry[i].partition.endcyl.current; for (j = 0; fdiskTags[j].tag; j++) { if (fdiskTags[j].tag == spec.entry[i].partition.type.current) { partitions[i].type = fdiskTags[j].type; strcpy(partitions[i].tagName, fdiskTags[j].tagName); break; } } } return 0; } int findAllPartitions(struct deviceInfo * devices, struct partitionTable * table) { int numPartitions; int i; struct partition parts[16]; struct partition * allParts = NULL; int numAllParts = 0; if (!devices) { /* FIXME: memory leak for internal structures */ devices = alloca(sizeof(*devices) * MAX_NUM_DRIVES); if (findDrivesPresent(devices, NULL)) return INST_ERROR; } winStatus(30, 3, _("Hard Drives"), _("Scanning hard drives...")); for (i = 0; devices[i].deviceName; i++) { findPartitions(devices[i].deviceName, &numPartitions, parts); if (!numPartitions) continue; if (!numAllParts) { numAllParts = numPartitions; allParts = malloc(sizeof(*allParts) * numAllParts); memcpy(allParts, parts, sizeof(*allParts) * numAllParts); } else { allParts = realloc(allParts, sizeof(*allParts) * (numAllParts + numPartitions)); memcpy(allParts + numAllParts, parts, sizeof(*allParts) * numPartitions); numAllParts += numPartitions; } } table->count = numAllParts; table->parts = allParts; newtPopWindow(); return 0; } static int findDrivesPresent(struct deviceInfo * drives, int * numPtr) { struct deviceInfo * scsi = NULL, * ide = NULL; int num = 0; int i; /* FIXME: this results in memory leaks via the strings inside of the decice structures! */ if (scsiDeviceAvailable()) { if (scsiGetDevices(&scsi)) return INST_ERROR; } if (ideGetDevices(&ide)) return INST_ERROR; i = 0, num = 0; while (ide[i].deviceName) { if (ide[i].type == DEVICE_HD) drives[num++] = ide[i]; i++; } i = 0; while (scsi && scsi[i].deviceName) { if (scsi[i].type == DEVICE_HD) drives[num++] = scsi[i]; i++; } drives[num].deviceName = NULL; if (numPtr) *numPtr = num; return 0; } int getDriveList(char *** drives, int * num) { struct deviceInfo drivesPresent[MAX_NUM_DRIVES]; int rc; int i; if ((rc = findDrivesPresent(drivesPresent, num))) return rc; *drives = malloc(sizeof(char *) * (*num + 1)); for (i = 0; i < *num; i++) { (*drives)[i] = drivesPresent[i].deviceName; } (*drives)[i] = NULL; return 0; } int partitionDrives(void) { struct deviceInfo drivesPresent[MAX_NUM_DRIVES]; int numDrivesPresent = 0; int childpid; int i, fd; int haveEdited = 0; char devBuf[100], idBuf[3]; char * driveText[50]; struct deviceInfo * currhd; int status; int reboot = 0; char * cmd; char * text; int rc, driveNum = 0; if (!access("/sbin/fdisk", X_OK)) cmd = "/sbin/fdisk"; else cmd = "/usr/bin/fdisk"; findDrivesPresent(drivesPresent, &numDrivesPresent); if (!numDrivesPresent) { newtWinMessage(_("Hard Drives"), _("Ok"), _("You don't have any hard drives available! " "You probably forgot to configure a SCSI " "controller.")); return INST_ERROR; } #ifdef __i386__ text = _("To install Red Hat Linux, you must have at least one parition " "of 150 MB dedicated to Linux. We suggest placing that partition " "on one of the first two hard drives in your system so you can " "boot into Linux with LILO."); #else text = _("To install Red Hat Linux, you must have at least one parition " "of 150 MB dedicated to Linux."); #endif for (i = 0; i < numDrivesPresent; i++) { sprintf(devBuf, "/dev/%s", drivesPresent[i].deviceName); if (!strncmp(drivesPresent[i].deviceName, "sd", 2)) { sprintf(idBuf, "%d", drivesPresent[i].id); strcat(devBuf, " - SCSI ID "); strcat(devBuf, idBuf); } strcat(devBuf, " - Model "); strcat(devBuf, drivesPresent[i].info); /* truncate at 50 columns for now */ devBuf[50] = '\0'; driveText[i] = alloca(strlen(devBuf) + 1); strcpy(driveText[i], devBuf); } driveText[i] = NULL; do { rc = newtWinMenu(_("Partition Disks"), text, 56, 5, 6, 5, driveText, &driveNum, _("Done"), _("Edit"), _("Back"), NULL); if (rc == 2 || rc == 0) { haveEdited = 1; currhd = drivesPresent + driveNum; sprintf(devBuf, "/tmp/%s", currhd->deviceName); if (devMakeInode(currhd->deviceName, devBuf)) return 0; newtSuspend(); for (i = 0; i < 25; i++) puts(""); printf("This is the fdisk program for partitioning your drive. It " "is running\non /dev/%s.\n\n", currhd->deviceName); logMessage("running fdisk on %s", devBuf); if (!(childpid = fork())) { execl(cmd, cmd, devBuf, NULL); return -1; } waitpid(childpid, &status, 0); newtResume(); } } while (rc == 2 || rc == 0); if (haveEdited) { for (i = 0; i < numDrivesPresent; i++) { sprintf(devBuf, "/tmp/%s", drivesPresent[i].deviceName); if (devMakeInode(drivesPresent[i].deviceName, devBuf)) return INST_ERROR; fd = open(devBuf, O_RDONLY); unlink(devBuf); if (fd < 0) reboot = 1; if (ioctl(fd, BLKRRPART, 0)) reboot = 1; close(fd); } } if (reboot) needReboot(); if (rc == 3) return INST_CANCEL; return 0; } void needReboot(void) { newtWinMessage(_("Reboot Needed"), _("Ok"), _("The kernel is unable to read your new partitioning " "information, probably because you modified extended " "partitions. While this is not critical, you must " "reboot your machine before proceeding. Insert the " "Red Hat boot disk now and press Return to reboot " "your system.\n\n" "If you have a ZIP or JAZ drive, make sure there is " "a disk in the drive as an empty SCSI drive can also " "cause this problem.")); newtFinished(); exit(0); }