Index: head/usr.sbin/sade/devices.c =================================================================== --- head/usr.sbin/sade/devices.c (revision 227938) +++ head/usr.sbin/sade/devices.c (revision 227939) @@ -1,345 +1,343 @@ /* * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sade.h" #include #include #include #include #include #include #include #include #include /* how much to bias minor number for a given /dev/s slice */ #define SLICE_DELTA (0x10000) static Device *Devices[DEV_MAX]; static int numDevs; #define DEVICE_ENTRY(type, name, descr, max) { type, name, descr, max } #define DISK(name, descr, max) \ DEVICE_ENTRY(DEVICE_TYPE_DISK, name, descr, max) static struct _devname { DeviceType type; char *name; char *description; int max; } device_names[] = { DISK("da%d", "SCSI disk device", 16), DISK("ad%d", "ATA/IDE disk device", 16), DISK("ar%d", "ATA/IDE RAID device", 16), DISK("afd%d", "ATAPI/IDE floppy device", 4), DISK("mlxd%d", "Mylex RAID disk", 4), DISK("amrd%d", "AMI MegaRAID drive", 4), DISK("idad%d", "Compaq RAID array", 4), DISK("twed%d", "3ware ATA RAID array", 4), DISK("aacd%d", "Adaptec FSA RAID array", 4), DISK("ipsd%d", "IBM ServeRAID RAID array", 4), DISK("mfid%d", "LSI MegaRAID SAS array", 4), { 0, NULL, NULL, 0 }, }; Device * new_device(char *name) { Device *dev; dev = safe_malloc(sizeof(Device)); bzero(dev, sizeof(Device)); if (name) SAFE_STRCPY(dev->name, name); return dev; } /* Stubs for unimplemented strategy routines */ Boolean dummyInit(Device *dev) { return TRUE; } FILE * dummyGet(Device *dev, char *dist, Boolean probe) { return NULL; } void dummyShutdown(Device *dev) { return; } static int deviceTry(struct _devname dev, char *try, int i) { int fd; char unit[80]; snprintf(unit, sizeof unit, dev.name, i); snprintf(try, FILENAME_MAX, "/dev/%s", unit); if (isDebug()) msgDebug("deviceTry: attempting to open %s\n", try); fd = open(try, O_RDONLY); if (fd >= 0) { if (isDebug()) msgDebug("deviceTry: open of %s succeeded.\n", try); } return fd; } /* Register a new device in the devices array */ Device * -deviceRegister(char *name, char *desc, char *devname, DeviceType type, Boolean enabled, +deviceRegister(char *name, char *desc, char *devname, DeviceType type, Boolean (*init)(Device *), FILE * (*get)(Device *, char *, Boolean), void (*shutdown)(Device *), void *private) { Device *newdev = NULL; if (numDevs == DEV_MAX) msgFatal("Too many devices found!"); else { newdev = new_device(name); newdev->description = desc; newdev->devname = devname; newdev->type = type; - newdev->enabled = enabled; newdev->init = init ? init : dummyInit; newdev->get = get ? get : dummyGet; newdev->shutdown = shutdown ? shutdown : dummyShutdown; newdev->private = private; Devices[numDevs] = newdev; Devices[++numDevs] = NULL; } return newdev; } /* Reset the registered device chain */ void deviceReset(void) { int i; for (i = 0; i < numDevs; i++) { DEVICE_SHUTDOWN(Devices[i]); /* XXX this potentially leaks Devices[i]->private if it's being * used to point to something dynamic, but you're not supposed * to call this routine at such times that some open instance * has its private ptr pointing somewhere anyway. XXX */ free(Devices[i]); } Devices[numDevs = 0] = NULL; } /* Get all device information for devices we have attached */ void deviceGetAll(void) { int i, j, fd; char **names; msgNotify("Probing devices, please wait (this can take a while)..."); /* Next, try to find all the types of devices one might need * during the second stage of the installation. */ for (i = 0; device_names[i].name; i++) { for (j = 0; j < device_names[i].max; j++) { char try[FILENAME_MAX]; switch(device_names[i].type) { case DEVICE_TYPE_DISK: fd = deviceTry(device_names[i], try, j); break; default: break; } } } /* Finally, go get the disks and look for DOS partitions to register */ if ((names = Disk_Names()) != NULL) { int i; for (i = 0; names[i]; i++) { Disk *d; /* Ignore memory disks */ if (!strncmp(names[i], "md", 2)) continue; /* * XXX * Due to unknown reasons, Disk_Names() returns SCSI CDROM as a * valid disk. This is main reason why sysinstall presents SCSI * CDROM to available disks in Fdisk/Label menu. In addition, * adding a blank SCSI CDROM to the menu generates floating point * exception in sparc64. Disk_Names() just extracts sysctl * "kern.disks". Why GEOM treats SCSI CDROM as a disk is beyond * me and that should be investigated. * For temporary workaround, ignore SCSI CDROM device. */ if (!strncmp(names[i], "cd", 2)) continue; d = Open_Disk(names[i]); if (!d) { msgDebug("Unable to open disk %s\n", names[i]); continue; } - deviceRegister(names[i], names[i], d->name, DEVICE_TYPE_DISK, FALSE, + deviceRegister(names[i], names[i], d->name, DEVICE_TYPE_DISK, dummyInit, dummyGet, dummyShutdown, d); if (isDebug()) msgDebug("Found a disk device named %s\n", names[i]); #if 0 /* Look for existing DOS partitions to register as "DOS media devices" */ for (c1 = d->chunks->part; c1; c1 = c1->next) { if (c1->type == fat || c1->type == efi || c1->type == extended) { Device *dev; char devname[80]; /* Got one! */ snprintf(devname, sizeof devname, "/dev/%s", c1->name); - dev = deviceRegister(c1->name, c1->name, strdup(devname), DEVICE_TYPE_DOS, TRUE, + dev = deviceRegister(c1->name, c1->name, strdup(devname), DEVICE_TYPE_DOS, mediaInitDOS, mediaGetDOS, mediaShutdownDOS, NULL); dev->private = c1; if (isDebug()) msgDebug("Found a DOS partition %s on drive %s\n", c1->name, d->name); } } #endif } free(names); } dialog_clear_norefresh(); } /* Rescan all devices, after closing previous set - convenience function */ void deviceRescan(void) { deviceReset(); deviceGetAll(); } /* * Find all devices that match the criteria, allowing "wildcarding" as well * by allowing NULL or ANY values to match all. The array returned is static * and may be used until the next invocation of deviceFind(). */ Device ** deviceFind(char *name, DeviceType class) { static Device *found[DEV_MAX]; int i, j; j = 0; for (i = 0; i < numDevs; i++) { if ((!name || !strcmp(Devices[i]->name, name)) && (class == DEVICE_TYPE_ANY || class == Devices[i]->type)) found[j++] = Devices[i]; } found[j] = NULL; return j ? found : NULL; } Device ** deviceFindDescr(char *name, char *desc, DeviceType class) { static Device *found[DEV_MAX]; int i, j; j = 0; for (i = 0; i < numDevs; i++) { if ((!name || !strcmp(Devices[i]->name, name)) && (!desc || !strcmp(Devices[i]->description, desc)) && (class == DEVICE_TYPE_ANY || class == Devices[i]->type)) found[j++] = Devices[i]; } found[j] = NULL; return j ? found : NULL; } int deviceCount(Device **devs) { int i; if (!devs) return 0; for (i = 0; devs[i]; i++); return i; } /* * Create a menu listing all the devices of a certain type in the system. * The passed-in menu is expected to be a "prototype" from which the new * menu is cloned. */ DMenu * -deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)(dialogMenuItem *d), int (*check)(dialogMenuItem *d)) +deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)(dialogMenuItem *d)) { Device **devs; int numdevs; DMenu *tmp = NULL; int i, j; devs = deviceFind(NULL, type); numdevs = deviceCount(devs); if (!numdevs) return NULL; tmp = (DMenu *)safe_malloc(sizeof(DMenu) + (sizeof(dialogMenuItem) * (numdevs + 1))); bcopy(menu, tmp, sizeof(DMenu)); for (i = 0; devs[i]; i++) { tmp->items[i].prompt = devs[i]->name; for (j = 0; j < numDevs; j++) { if (devs[i] == Devices[j]) { tmp->items[i].title = Devices[j]->description; break; } } if (j == numDevs) tmp->items[i].title = ""; tmp->items[i].fire = hook; - tmp->items[i].checked = check; } tmp->items[i].title = NULL; return tmp; } Index: head/usr.sbin/sade/disks.c =================================================================== --- head/usr.sbin/sade/disks.c (revision 227938) +++ head/usr.sbin/sade/disks.c (revision 227939) @@ -1,1037 +1,975 @@ /* * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sade.h" #include #include #include #include #include #include #ifdef WITH_SLICES enum size_units_t { UNIT_BLOCKS, UNIT_KILO, UNIT_MEG, UNIT_GIG, UNIT_SIZE }; #ifdef PC98 #define SUBTYPE_FREEBSD 50324 #define SUBTYPE_FAT 37218 #else #define SUBTYPE_FREEBSD 165 #define SUBTYPE_FAT 6 #endif #define SUBTYPE_EFI 239 #ifdef PC98 #define OTHER_SLICE_VALUES \ "Other popular values are 37218 for a\n" \ "DOS FAT partition.\n\n" #else #define OTHER_SLICE_VALUES \ "Other popular values are 6 for a\n" \ "DOS FAT partition, 131 for a Linux ext2fs partition, or\n" \ "130 for a Linux swap partition.\n\n" #endif #define NON_FREEBSD_NOTE \ "Note: If you choose a non-FreeBSD partition type, it will not\n" \ "be formatted or otherwise prepared, it will simply reserve space\n" \ "for you to use another tool, such as DOS format, to later format\n" \ "and actually use the partition." /* Where we start displaying chunk information on the screen */ #define CHUNK_START_ROW 5 /* Where we keep track of MBR chunks */ #define CHUNK_INFO_ENTRIES 16 static struct chunk *chunk_info[CHUNK_INFO_ENTRIES]; static int current_chunk; static void diskPartitionNonInteractive(Device *dev); #if !defined(__ia64__) static u_char * bootalloc(char *name, size_t *size); #endif static void record_chunks(Disk *d) { struct chunk *c1 = NULL; int i = 0; daddr_t last_free = 0; if (!d->chunks) msgFatal("No chunk list found for %s!", d->name); for (c1 = d->chunks->part; c1; c1 = c1->next) { if (c1->type == unused && c1->size > last_free) { last_free = c1->size; current_chunk = i; } chunk_info[i++] = c1; } chunk_info[i] = NULL; if (current_chunk >= i) current_chunk = i - 1; } static daddr_t Total; static void check_geometry(Disk *d) { int sg; #ifdef PC98 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) #else if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) #endif { dialog_clear_norefresh(); sg = msgYesNo("WARNING: It is safe to use a geometry of %lu/%lu/%lu for %s on\n" "computers with modern BIOS versions. If this disk is to be used\n" "on an old machine it is recommended that it does not have more\n" "than 65535 cylinders, more than 255 heads, or more than\n" #ifdef PC98 "255" #else "63" #endif " sectors per track.\n" "\n" "Would you like to keep using the current geometry?\n", d->bios_cyl, d->bios_hd, d->bios_sect, d->name); if (sg == 1) { Sanitize_Bios_Geom(d); msgConfirm("A geometry of %lu/%lu/%lu was calculated for %s.\n" "\n" "If you are not sure about this, please consult the Hardware Guide\n" "in the Documentation submenu or use the (G)eometry command to\n" "change it. Remember: you need to enter whatever your BIOS thinks\n" "the geometry is! For IDE, it's what you were told in the BIOS\n" "setup. For SCSI, it's the translation mode your controller is\n" "using. Do NOT use a ``physical geometry''.\n", d->bios_cyl, d->bios_hd, d->bios_sect, d->name); } } } static void print_chunks(Disk *d, int u) { int row; int i; daddr_t sz; char *szstr; szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" : (u == UNIT_KILO ? "KB" : "ST"))); Total = 0; for (i = 0; chunk_info[i]; i++) Total += chunk_info[i]->size; attrset(A_NORMAL); mvaddstr(0, 0, "Disk name:\t"); clrtobot(); attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); mvprintw(1, 0, "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %jd sectors (%jdMB)", d->bios_cyl, d->bios_hd, d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect, (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect / (1024/512) / 1024); mvprintw(3, 0, "%6s %10s(%s) %10s %8s %6s %10s %8s %8s", "Offset", "Size", szstr, "End", "Name", "PType", "Desc", "Subtype", "Flags"); for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { switch(u) { default: /* fall thru */ case UNIT_BLOCKS: sz = chunk_info[i]->size; break; case UNIT_KILO: sz = chunk_info[i]->size / (1024/512); break; case UNIT_MEG: sz = chunk_info[i]->size / (1024/512) / 1024; break; case UNIT_GIG: sz = chunk_info[i]->size / (1024/512) / 1024 / 1024; break; } if (i == current_chunk) attrset(ATTR_SELECTED); mvprintw(row, 0, "%10jd %10jd %10jd %8s %6d %10s %8d\t%-6s", (intmax_t)chunk_info[i]->offset, (intmax_t)sz, (intmax_t)chunk_info[i]->end, chunk_info[i]->name, chunk_info[i]->type, slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); if (i == current_chunk) attrset(A_NORMAL); } } static void print_command_summary(void) { mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); mvprintw(16, 0, "A = Use Entire Disk G = set Drive Geometry C = Create Slice"); mvprintw(17, 0, "D = Delete Slice Z = Toggle Size Units S = Set Bootable | = Expert m."); mvprintw(18, 0, "T = Change Type U = Undo All Changes W = Write Changes Q = Finish"); mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); move(0, 0); } #ifdef PC98 static void getBootMgr(char *dname, u_char **bootipl, size_t *bootipl_size, u_char **bootmenu, size_t *bootmenu_size) { static u_char *boot0; static size_t boot0_size; static u_char *boot05; static size_t boot05_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of IPL the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuIPLType.title = str; i = dmenuOpenSimple(&MenuIPLType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else BootMgr = 1; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootipl = boot0; *bootipl_size = boot0_size; if (!boot05) boot05 = bootalloc("boot0.5", &boot05_size); *bootmenu = boot05; *bootmenu_size = boot05_size; return; case 1: default: break; } } *bootipl = NULL; *bootipl_size = 0; *bootmenu = NULL; *bootmenu_size = 0; } #else static void getBootMgr(char *dname, u_char **bootCode, size_t *bootCodeSize) { #if defined(__i386__) || defined(__amd64__) /* only meaningful on x86 */ static u_char *mbr, *boot0; static size_t mbr_size, boot0_size; char str[80]; char *cp; int i = 0; cp = variable_get(VAR_BOOTMGR); if (!cp) { /* Figure out what kind of MBR the user wants */ sprintf(str, "Install Boot Manager for drive %s?", dname); MenuMBRType.title = str; i = dmenuOpenSimple(&MenuMBRType, FALSE); } else { if (!strncmp(cp, "boot", 4)) BootMgr = 0; else if (!strcmp(cp, "standard")) BootMgr = 1; else BootMgr = 2; } if (cp || i) { switch (BootMgr) { case 0: if (!boot0) boot0 = bootalloc("boot0", &boot0_size); *bootCode = boot0; *bootCodeSize = boot0_size; return; case 1: if (!mbr) mbr = bootalloc("mbr", &mbr_size); *bootCode = mbr; *bootCodeSize = mbr_size; return; case 2: default: break; } } #endif *bootCode = NULL; *bootCodeSize = 0; } #endif #endif /* WITH_SLICES */ -int -diskGetSelectCount(Device ***devs) -{ - int i, cnt, enabled; - char *cp; - Device **dp; - - cp = variable_get(VAR_DISK); - dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); - cnt = deviceCount(dp); - if (!cnt) - return -1; - for (i = 0, enabled = 0; i < cnt; i++) { - if (dp[i]->enabled) - ++enabled; - } - return enabled; -} - #ifdef WITH_SLICES void diskPartition(Device *dev) { char *cp, *p; int rv, key = 0; int i; Boolean chunking; char *msg = NULL; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif WINDOW *w = savescr(); Disk *d = (Disk *)dev->private; int size_unit; size_unit = UNIT_BLOCKS; chunking = TRUE; keypad(stdscr, TRUE); /* Flush both the dialog and curses library views of the screen since we don't always know who called us */ dialog_clear_norefresh(), clear(); current_chunk = 0; /* Set up the chunk array */ record_chunks(d); /* Give the user a chance to sanitize the disk geometry, if necessary */ check_geometry(d); while (chunking) { char *val, geometry[80]; /* Now print our overall state */ if (d) print_chunks(d, size_unit); print_command_summary(); if (msg) { attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); beep(); msg = NULL; } else { move(23, 0); clrtoeol(); } /* Get command character */ key = getch(); switch (toupper(key)) { case '\014': /* ^L (redraw) */ clear(); msg = NULL; break; case '\020': /* ^P */ case KEY_UP: case '-': if (current_chunk != 0) --current_chunk; break; case '\016': /* ^N */ case KEY_DOWN: case '+': case '\r': case '\n': if (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_HOME: current_chunk = 0; break; case KEY_END: while (chunk_info[current_chunk + 1]) ++current_chunk; break; case KEY_F(1): case '?': systemDisplayHelp("slice"); clear(); break; case 'A': case 'F': /* Undocumented magic Dangerously Dedicated mode */ #if !defined(__i386__) && !defined(__amd64__) rv = 1; #else /* The rest is only relevant on x86 */ cp = variable_get(VAR_DEDICATE_DISK); if (cp && !strcasecmp(cp, "always")) rv = 1; else if (toupper(key) == 'A') rv = 0; else { rv = msgYesNo("Do you want to do this with a true partition entry\n" "so as to remain cooperative with any future possible\n" "operating systems on the drive(s)?\n" "(See also the section about ``dangerously dedicated''\n" "disks in the FreeBSD FAQ.)"); if (rv == -1) rv = 0; } #endif All_FreeBSD(d, rv); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); clear(); break; case 'C': if (chunk_info[current_chunk]->type != unused) msg = "Slice in use, delete it first or move to an unused one."; else { char *val, tmp[20], name[16], *cp; daddr_t size; int subtype; chunk_e partitiontype; #ifdef PC98 snprintf(name, sizeof (name), "%s", "FreeBSD"); val = msgGetInput(name, "Please specify the name for new FreeBSD slice."); if (val) strncpy(name, val, sizeof (name)); #else name[0] = '\0'; #endif snprintf(tmp, 20, "%jd", (intmax_t)chunk_info[current_chunk]->size); val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" "or append a trailing `M' for megabytes (e.g. 20M)."); if (val && (size = strtoimax(val, &cp, 0)) > 0) { if (*cp && toupper(*cp) == 'M') size *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') size *= ONE_GIG; sprintf(tmp, "%d", SUBTYPE_FREEBSD); val = msgGetInput(tmp, "Enter type of partition to create:\n\n" "Pressing Enter will choose the default, a native FreeBSD\n" "slice (type %u). " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, (chunk_info[current_chunk]->flags & CHUNK_ALIGN), name); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } } clear(); } break; case KEY_DC: case 'D': if (chunk_info[current_chunk]->type == unused) msg = "Slice is already unused!"; else { Delete_Chunk(d, chunk_info[current_chunk]); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } break; case 'T': if (chunk_info[current_chunk]->type == unused) msg = "Slice is currently unused (use create instead)"; else { char *val, tmp[20]; int subtype; chunk_e partitiontype; sprintf(tmp, "%d", chunk_info[current_chunk]->subtype); val = msgGetInput(tmp, "New partition type:\n\n" "Pressing Enter will use the current type. To choose a native\n" "FreeBSD slice enter %u. " OTHER_SLICE_VALUES NON_FREEBSD_NOTE, SUBTYPE_FREEBSD); if (val && (subtype = strtol(val, NULL, 0)) > 0) { if (subtype == SUBTYPE_FREEBSD) partitiontype = freebsd; else if (subtype == SUBTYPE_FAT) partitiontype = fat; else if (subtype == SUBTYPE_EFI) partitiontype = efi; else #ifdef PC98 partitiontype = pc98; #else partitiontype = mbr; #endif chunk_info[current_chunk]->type = partitiontype; chunk_info[current_chunk]->subtype = subtype; } } break; case 'G': snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" "Don't forget to use the two slash (/) separator characters!\n" "It's not possible to parse the field without them."); if (val) { long nc, nh, ns; nc = strtol(val, &val, 0); nh = strtol(val + 1, &val, 0); ns = strtol(val + 1, 0, 0); Set_Bios_Geom(d, nc, nh, ns); } clear(); break; case 'S': /* Clear active states so we won't have two */ for (i = 0; (chunk_info[i] != NULL) && (i < CHUNK_INFO_ENTRIES); i++) chunk_info[i]->flags &= !CHUNK_ACTIVE; /* Set Bootable */ chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; break; case 'U': if (!variable_cmp(DISK_LABELLED, "written")) { msgConfirm("You've already written this information out - you\n" "can't undo it."); } else if (!msgNoYes("Are you SURE you want to Undo everything?")) { char cp[BUFSIZ]; sstrncpy(cp, d->name, sizeof cp); Free_Disk(dev->private); d = Open_Disk(cp); if (!d) msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); dev->private = d; variable_unset(DISK_PARTITIONED); variable_unset(DISK_LABELLED); if (d) record_chunks(d); } clear(); break; case 'W': if (!msgNoYes("WARNING: You are about to modify an EXISTING installation.\n" "You should simply type Q when you are finished\n" "here and write to the disk from the label editor.\n\n" "Are you absolutely sure you want to continue?")) { variable_set2(DISK_PARTITIONED, "yes", 0); #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested a FreeBSD Boot Manager -- both would be fatal in * this case. */ /* * Don't offer to update the IPL on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); else { bootipl = NULL; bootipl_size = 0; bootmenu = NULL; bootmenu_size = 0; } Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has * requested booteasy or a "standard" MBR -- both would be * fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first * "real" chunk looks like a FreeBSD "all disk" partition, * or the disk is entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) getBootMgr(d->name, &mbrContents, &mbrSize); else { mbrContents = NULL; mbrSize = 0; } Set_Boot_Mgr(d, mbrContents, mbrSize); #endif - if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) + if (DITEM_STATUS(diskPartitionWrite(dev)) != DITEM_SUCCESS) msgConfirm("Disk partition write returned an error status!"); else msgConfirm("Wrote FDISK partition information out successfully."); } clear(); break; case '|': if (!msgNoYes("Are you SURE you want to go into Wizard mode?\n" "No seat belts whatsoever are provided!")) { clear(); refresh(); slice_wizard(d); variable_set2(DISK_PARTITIONED, "yes", 0); record_chunks(d); } else msg = "Wise choice!"; clear(); break; case '\033': /* ESC */ case 'Q': chunking = FALSE; #ifdef PC98 /* * Don't trash the IPL if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * a FreeBSD Boot Manager -- both would be fatal in this case. */ /* * Don't offer to update the IPL on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); if (bootipl != NULL && bootmenu != NULL) Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); } } #else /* * Don't trash the MBR if the first (and therefore only) chunk * is marked for a truly dedicated disk (i.e., the disklabel * starts at sector 0), even in cases where the user has requested * booteasy or a "standard" MBR -- both would be fatal in this case. */ /* * Don't offer to update the MBR on this disk if the first "real" * chunk looks like a FreeBSD "all disk" partition, or the disk is * entirely FreeBSD. */ if ((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) { if (variable_cmp(DISK_PARTITIONED, "written")) { getBootMgr(d->name, &mbrContents, &mbrSize); if (mbrContents != NULL) Set_Boot_Mgr(d, mbrContents, mbrSize); } } #endif break; case 'Z': size_unit = (size_unit + 1) % UNIT_SIZE; break; default: beep(); msg = "Type F1 or ? for help"; break; } } p = CheckRules(d); if (p) { char buf[FILENAME_MAX]; use_helpline("Press F1 to read more about disk slices."); use_helpfile(systemHelpFile("partition", buf)); if (!variable_get(VAR_NO_WARN)) dialog_mesgbox("Disk slicing warning:", p, -1, -1); free(p); } restorescr(w); } #endif /* WITH_SLICES */ #if !defined(__ia64__) static u_char * bootalloc(char *name, size_t *size) { char buf[FILENAME_MAX]; struct stat sb; snprintf(buf, sizeof buf, "/boot/%s", name); if (stat(buf, &sb) != -1) { int fd; fd = open(buf, O_RDONLY); if (fd != -1) { u_char *cp; cp = malloc(sb.st_size); if (read(fd, cp, sb.st_size) != sb.st_size) { free(cp); close(fd); msgDebug("bootalloc: couldn't read %ld bytes from %s\n", (long)sb.st_size, buf); return NULL; } close(fd); if (size != NULL) *size = sb.st_size; return cp; } msgDebug("bootalloc: couldn't open %s\n", buf); } else msgDebug("bootalloc: can't stat %s\n", buf); return NULL; } #endif /* !__ia64__ */ -#ifdef WITH_SLICES +#ifdef WITH_SLICES static int partitionHook(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find disk %s!", selected->prompt); return DITEM_FAILURE; } - /* Toggle enabled status? */ - if (!devs[0]->enabled) { - devs[0]->enabled = TRUE; - diskPartition(devs[0]); - } - else - devs[0]->enabled = FALSE; + diskPartition(devs[0]); return DITEM_SUCCESS; } -static int -partitionCheck(dialogMenuItem *selected) -{ - Device **devs = NULL; - - devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); - if (!devs || devs[0]->enabled == FALSE) - return FALSE; - return TRUE; -} - int diskPartitionEditor(dialogMenuItem *self) { DMenu *menu; Device **devs; - int i, cnt, devcnt; - cnt = diskGetSelectCount(&devs); - devcnt = deviceCount(devs); - if (cnt == -1) { + devs = deviceFind(variable_get(VAR_DISK), DEVICE_TYPE_DISK); + if (devs == NULL) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } - else if (cnt) { - /* Some are already selected */ - for (i = 0; i < devcnt; i++) { - if (devs[i]->enabled) { - if (variable_get(VAR_NONINTERACTIVE) && - !variable_get(VAR_DISKINTERACTIVE)) - diskPartitionNonInteractive(devs[i]); - else - diskPartition(devs[i]); - } - } - } else { /* No disks are selected, fall-back case now */ - if (devcnt == 1) { - devs[0]->enabled = TRUE; + int cnt = deviceCount(devs); + + if (cnt == 1) { if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) diskPartitionNonInteractive(devs[0]); else diskPartition(devs[0]); return DITEM_SUCCESS; } else { - menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); + int result; + + menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook); if (!menu) { msgConfirm("No devices suitable for installation found!\n\n" "Please verify that your disk controller (and attached drives)\n" "were detected properly. This can be done by pressing the\n" "[Scroll Lock] key and using the Arrow keys to move back to\n" "the boot messages. Press [Scroll Lock] again to return."); return DITEM_FAILURE; } - else { - i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; - free(menu); - } - return i; + + result = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; + free(menu); + return result; } } return DITEM_SUCCESS; } #endif /* WITH_SLICES */ int -diskPartitionWrite(dialogMenuItem *self) +diskPartitionWrite(Device *dev) { - Device **devs; - int i; - - if (!variable_cmp(DISK_PARTITIONED, "written")) - return DITEM_SUCCESS; - - devs = deviceFind(NULL, DEVICE_TYPE_DISK); - if (!devs) { - msgConfirm("Unable to find any disks to write to??"); - return DITEM_FAILURE; - } - if (isDebug()) - msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); - for (i = 0; devs[i]; i++) { - Disk *d = (Disk *)devs[i]->private; + Disk *d = (Disk *)dev->private; #if !defined(__ia64__) - static u_char *boot1; + static u_char *boot1; #endif #if defined(__i386__) || defined(__amd64__) - static u_char *boot2; + static u_char *boot2; #endif - if (!devs[i]->enabled) - continue; + if (!variable_cmp(DISK_PARTITIONED, "written")) + return DITEM_SUCCESS; #if defined(__i386__) || defined(__amd64__) - if (!boot1) boot1 = bootalloc("boot1", NULL); - if (!boot2) boot2 = bootalloc("boot2", NULL); - Set_Boot_Blocks(d, boot1, boot2); + if (!boot1) boot1 = bootalloc("boot1", NULL); + if (!boot2) boot2 = bootalloc("boot2", NULL); + Set_Boot_Blocks(d, boot1, boot2); #elif !defined(__ia64__) - if (!boot1) boot1 = bootalloc("boot1", NULL); - Set_Boot_Blocks(d, boot1, NULL); + if (!boot1) boot1 = bootalloc("boot1", NULL); + Set_Boot_Blocks(d, boot1, NULL); #endif - msgNotify("Writing partition information to drive %s", d->name); - if (!Fake && Write_Disk(d)) { - msgConfirm("ERROR: Unable to write data to disk %s!", d->name); - return DITEM_FAILURE; - } + msgNotify("Writing partition information to drive %s", d->name); + if (!Fake && Write_Disk(d)) { + msgConfirm("ERROR: Unable to write data to disk %s!", d->name); + return DITEM_FAILURE; } + /* Now it's not "yes", but "written" */ variable_set2(DISK_PARTITIONED, "written", 0); return DITEM_SUCCESS | DITEM_RESTORE; } #ifdef WITH_SLICES /* Partition a disk based wholly on which variables are set */ static void diskPartitionNonInteractive(Device *dev) { char *cp; int i, all_disk = 0; daddr_t sz; #ifdef PC98 u_char *bootipl; size_t bootipl_size; u_char *bootmenu; size_t bootmenu_size; #else u_char *mbrContents; size_t mbrSize; #endif Disk *d = (Disk *)dev->private; record_chunks(d); cp = variable_get(VAR_GEOMETRY); if (cp) { if (!strcasecmp(cp, "sane")) { #ifdef PC98 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256) #else if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) #endif { msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n", d->bios_cyl, d->bios_hd, d->bios_sect, d->name); Sanitize_Bios_Geom(d); msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n", d->name, d->bios_cyl, d->bios_hd, d->bios_sect); } } else { msgDebug("Setting geometry from script to: %s\n", cp); d->bios_cyl = strtol(cp, &cp, 0); d->bios_hd = strtol(cp + 1, &cp, 0); d->bios_sect = strtol(cp + 1, 0, 0); } } cp = variable_get(VAR_PARTITION); if (cp) { if (!strcmp(cp, "free")) { /* Do free disk space case */ for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least 10MB in size, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find any free space on this disk!"); return; } } else if (!strcmp(cp, "all")) { /* Do all disk space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, FALSE); } else if (!strcmp(cp, "exclusive")) { /* Do really-all-the-disk-space case */ msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); All_FreeBSD(d, all_disk = TRUE); } else if ((sz = strtoimax(cp, &cp, 0))) { /* Look for sz bytes free */ if (*cp && toupper(*cp) == 'M') sz *= ONE_MEG; else if (*cp && toupper(*cp) == 'G') sz *= ONE_GIG; for (i = 0; chunk_info[i]; i++) { /* If a chunk is at least sz MB, use it. */ if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN), "FreeBSD"); variable_set2(DISK_PARTITIONED, "yes", 0); break; } } if (!chunk_info[i]) { msgConfirm("Unable to find %jd free blocks on this disk!", (intmax_t)sz); return; } } else if (!strcmp(cp, "existing")) { /* Do existing FreeBSD case */ for (i = 0; chunk_info[i]; i++) { if (chunk_info[i]->type == freebsd) break; } if (!chunk_info[i]) { msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); return; } } else { msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); return; } if (!all_disk) { #ifdef PC98 getBootMgr(d->name, &bootipl, &bootipl_size, &bootmenu, &bootmenu_size); Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size); #else getBootMgr(d->name, &mbrContents, &mbrSize); Set_Boot_Mgr(d, mbrContents, mbrSize); #endif } variable_set2(DISK_PARTITIONED, "yes", 0); } } #endif /* WITH_SLICES */ Index: head/usr.sbin/sade/install.c =================================================================== --- head/usr.sbin/sade/install.c (revision 227938) +++ head/usr.sbin/sade/install.c (revision 227939) @@ -1,257 +1,248 @@ /* * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sade.h" #include #include #include #include #include #include #include #include #include #define MSDOSFS #include #include #include #undef MSDOSFS #include #include #include #include #include #include #define TERMCAP_FILE "/usr/share/misc/termcap" Boolean checkLabels(Boolean whinge) { Boolean status; /* Don't allow whinging if noWarn is set */ if (variable_get(VAR_NO_WARN)) whinge = FALSE; status = TRUE; HomeChunk = RootChunk = SwapChunk = NULL; TmpChunk = UsrChunk = VarChunk = NULL; #ifdef __ia64__ EfiChunk = NULL; #endif /* We don't need to worry about root/usr/swap if we're already multiuser */ return status; } #define QUEUE_YES 1 #define QUEUE_NO 0 static int performNewfs(PartInfo *pi, char *dname, int queue) { char buffer[LINE_MAX]; if (pi->do_newfs) { switch(pi->newfs_type) { case NEWFS_UFS: snprintf(buffer, LINE_MAX, "%s %s %s %s %s", NEWFS_UFS_CMD, pi->newfs_data.newfs_ufs.softupdates ? "-U" : "", pi->newfs_data.newfs_ufs.ufs1 ? "-O1" : "-O2", pi->newfs_data.newfs_ufs.user_options, dname); break; case NEWFS_MSDOS: snprintf(buffer, LINE_MAX, "%s %s", NEWFS_MSDOS_CMD, dname); break; case NEWFS_CUSTOM: snprintf(buffer, LINE_MAX, "%s %s", pi->newfs_data.newfs_custom.command, dname); break; } if (queue == QUEUE_YES) { command_shell_add(pi->mountpoint, buffer); return (0); } else return (vsystem(buffer)); } return (0); } /* Go newfs and/or mount all the filesystems we've been asked to */ int -installFilesystems(dialogMenuItem *self) +installFilesystems(Device *dev) { - int i; - Disk *disk; + Disk *disk = (Disk *)dev->private; Chunk *c1, *c2; - Device **devs; PartInfo *root; char dname[80]; Boolean upgrade = FALSE; /* If we've already done this, bail out */ if (!variable_cmp(DISK_LABELLED, "written")) return DITEM_SUCCESS; upgrade = !variable_cmp(SYSTEM_STATE, "upgrade"); if (!checkLabels(TRUE)) return DITEM_FAILURE; root = (RootChunk != NULL) ? (PartInfo *)RootChunk->private_data : NULL; command_clear(); /* Now buzz through the rest of the partitions and mount them too */ - devs = deviceFind(NULL, DEVICE_TYPE_DISK); - for (i = 0; devs[i]; i++) { - if (!devs[i]->enabled) - continue; - - disk = (Disk *)devs[i]->private; - if (!disk->chunks) { - msgConfirm("No chunk list found for %s!", disk->name); - return DITEM_FAILURE | DITEM_RESTORE; - } - for (c1 = disk->chunks->part; c1; c1 = c1->next) { + if (!disk->chunks) { + msgConfirm("No chunk list found for %s!", disk->name); + return DITEM_FAILURE | DITEM_RESTORE; + } + for (c1 = disk->chunks->part; c1; c1 = c1->next) { #ifdef __ia64__ - if (c1->type == part) { - c2 = c1; - { + if (c1->type == part) { + c2 = c1; + { #elif defined(__powerpc__) - if (c1->type == apple) { - for (c2 = c1->part; c2; c2 = c2->next) { + if (c1->type == apple) { + for (c2 = c1->part; c2; c2 = c2->next) { #else - if (c1->type == freebsd) { - for (c2 = c1->part; c2; c2 = c2->next) { + if (c1->type == freebsd) { + for (c2 = c1->part; c2; c2 = c2->next) { #endif - if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { - PartInfo *tmp = (PartInfo *)c2->private_data; + if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { + PartInfo *tmp = (PartInfo *)c2->private_data; - /* Already did root */ - if (c2 == RootChunk) - continue; + /* Already did root */ + if (c2 == RootChunk) + continue; - sprintf(dname, "/dev/%s", c2->name); + sprintf(dname, "/dev/%s", c2->name); - if (tmp->do_newfs && (!upgrade || - !msgNoYes("You are upgrading - are you SURE you" - " want to newfs /dev/%s?", c2->name))) - performNewfs(tmp, dname, QUEUE_YES); - else - command_shell_add(tmp->mountpoint, - "fsck_ffs -y /dev/%s", c2->name); - command_func_add(tmp->mountpoint, Mount, c2->name); - } - else if (c2->type == part && c2->subtype == FS_SWAP) { - char fname[80]; - int i; + if (tmp->do_newfs && (!upgrade || + !msgNoYes("You are upgrading - are you SURE you" + " want to newfs /dev/%s?", c2->name))) + performNewfs(tmp, dname, QUEUE_YES); + else + command_shell_add(tmp->mountpoint, + "fsck_ffs -y /dev/%s", c2->name); + command_func_add(tmp->mountpoint, Mount, c2->name); + } + else if (c2->type == part && c2->subtype == FS_SWAP) { + char fname[80]; + int i; - if (c2 == SwapChunk) - continue; - sprintf(fname, "/dev/%s", c2->name); - i = (Fake || swapon(fname)); - if (!i) { - dialog_clear_norefresh(); - msgNotify("Added %s as an additional swap device", fname); - } - else { - msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); - } - } - } - } - else if (c1->type == fat && c1->private_data && - (root->do_newfs || upgrade)) { - char name[FILENAME_MAX]; + if (c2 == SwapChunk) + continue; + sprintf(fname, "/dev/%s", c2->name); + i = (Fake || swapon(fname)); + if (!i) { + dialog_clear_norefresh(); + msgNotify("Added %s as an additional swap device", fname); + } + else { + msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); + } + } + } + } + else if (c1->type == fat && c1->private_data && + (root->do_newfs || upgrade)) { + char name[FILENAME_MAX]; - sprintf(name, "/%s", ((PartInfo *)c1->private_data)->mountpoint); - Mkdir(name); - } + sprintf(name, "/%s", ((PartInfo *)c1->private_data)->mountpoint); + Mkdir(name); + } #if defined(__ia64__) - else if (c1->type == efi && c1->private_data) { - PartInfo *pi = (PartInfo *)c1->private_data; + else if (c1->type == efi && c1->private_data) { + PartInfo *pi = (PartInfo *)c1->private_data; - sprintf(dname, "/dev/%s", c1->name); + sprintf(dname, "/dev/%s", c1->name); - if (pi->do_newfs && (!upgrade || - !msgNoYes("You are upgrading - are you SURE you want to " - "newfs /dev/%s?", c1->name))) - performNewfs(pi, dname, QUEUE_YES); - } + if (pi->do_newfs && (!upgrade || + !msgNoYes("You are upgrading - are you SURE you want to " + "newfs /dev/%s?", c1->name))) + performNewfs(pi, dname, QUEUE_YES); + } #endif - } } command_sort(); command_execute(); dialog_clear_norefresh(); return DITEM_SUCCESS | DITEM_RESTORE; } static char * getRelname(void) { static char buf[64]; size_t sz = (sizeof buf) - 1; if (sysctlbyname("kern.osrelease", buf, &sz, NULL, 0) != -1) { buf[sz] = '\0'; return buf; } else return ""; } /* Initialize various user-settable values to their defaults */ int installVarDefaults(dialogMenuItem *self) { /* Set default startup options */ variable_set2(VAR_RELNAME, getRelname(), 0); variable_set2(SYSTEM_STATE, "update", 0); variable_set2(VAR_NEWFS_ARGS, "-b 16384 -f 2048", 0); variable_set2(VAR_CONSTERM, "NO", 0); return DITEM_SUCCESS; } /* Load the environment up from various system configuration files */ void installEnvironment(void) { } Index: head/usr.sbin/sade/label.c =================================================================== --- head/usr.sbin/sade/label.c (revision 227938) +++ head/usr.sbin/sade/label.c (revision 227939) @@ -1,1703 +1,1644 @@ /* * $FreeBSD$ * * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "sade.h" #include #include #include #include #include #include #define AUTO_HOME 0 /* do not create /home automatically */ /* * Everything to do with editing the contents of disk labels. */ /* A nice message we use a lot in the disklabel editor */ #define MSG_NOT_APPLICABLE "That option is not applicable here" /* Where to start printing the freebsd slices */ #define CHUNK_SLICE_START_ROW 2 #define CHUNK_PART_START_ROW 11 /* The smallest filesystem we're willing to create */ #define FS_MIN_SIZE ONE_MEG /* * Minimum partition sizes */ #if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) || defined(__amd64__) #define ROOT_MIN_SIZE 128 #else #define ROOT_MIN_SIZE 118 #endif #define SWAP_MIN_SIZE 32 #define USR_MIN_SIZE 128 #define VAR_MIN_SIZE 20 #define TMP_MIN_SIZE 20 #define HOME_MIN_SIZE 20 /* * Swap size limit for auto-partitioning (4G). */ #define SWAP_AUTO_LIMIT_SIZE 4096 /* * Default partition sizes. If we do not have sufficient disk space * for this configuration we scale things relative to the NOM vs DEFAULT * sizes. If the disk is larger then /home will get any remaining space. */ #define ROOT_DEFAULT_SIZE 512 #define USR_DEFAULT_SIZE 8192 #define VAR_DEFAULT_SIZE 1024 #define TMP_DEFAULT_SIZE 512 #define HOME_DEFAULT_SIZE USR_DEFAULT_SIZE /* * Nominal partition sizes. These are used to scale the default sizes down * when we have insufficient disk space. If this isn't sufficient we scale * down using the MIN sizes instead. */ #define ROOT_NOMINAL_SIZE 256 #define USR_NOMINAL_SIZE 1536 #define VAR_NOMINAL_SIZE 128 #define TMP_NOMINAL_SIZE 128 #define HOME_NOMINAL_SIZE USR_NOMINAL_SIZE /* The bottom-most row we're allowed to scribble on */ #define CHUNK_ROW_MAX 16 /* All the chunks currently displayed on the screen */ static struct { struct chunk *c; PartType type; } label_chunk_info[MAX_CHUNKS + 1]; static int here; /*** with this value we try to track the most recently added label ***/ static int label_focus = 0, pslice_focus = 0; static int diskLabel(Device *dev); static int diskLabelNonInteractive(Device *dev); -static char *try_auto_label(Device **devs, Device *dev, int perc, int *req); +static char *try_auto_label(Device *dev, int perc, int *req); static int labelHook(dialogMenuItem *selected) { Device **devs = NULL; devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("Unable to find disk %s!", selected->prompt); return DITEM_FAILURE; } - /* Toggle enabled status? */ - if (!devs[0]->enabled) { - devs[0]->enabled = TRUE; - diskLabel(devs[0]); - } - else - devs[0]->enabled = FALSE; + diskLabel(devs[0]); return DITEM_SUCCESS; } -static int -labelCheck(dialogMenuItem *selected) -{ - Device **devs = NULL; - - devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); - if (!devs || devs[0]->enabled == FALSE) - return FALSE; - return TRUE; -} - int diskLabelEditor(dialogMenuItem *self) { DMenu *menu; Device **devs; - int i, cnt; + int result; - i = 0; - cnt = diskGetSelectCount(&devs); - if (cnt == -1) { + devs = deviceFind(variable_get(VAR_DISK), DEVICE_TYPE_DISK); + if (devs == NULL) { msgConfirm("No disks found! Please verify that your disk controller is being\n" "properly probed at boot time. See the Hardware Guide on the\n" "Documentation menu for clues on diagnosing this type of problem."); return DITEM_FAILURE; } - else if (cnt) { - /* Some are already selected */ - if (variable_get(VAR_NONINTERACTIVE) && - !variable_get(VAR_DISKINTERACTIVE)) - i = diskLabelNonInteractive(NULL); - else - i = diskLabel(NULL); - } else { /* No disks are selected, fall-back case now */ - cnt = deviceCount(devs); + int cnt = deviceCount(devs); if (cnt == 1) { - devs[0]->enabled = TRUE; if (variable_get(VAR_NONINTERACTIVE) && !variable_get(VAR_DISKINTERACTIVE)) - i = diskLabelNonInteractive(devs[0]); + result = diskLabelNonInteractive(devs[0]); else - i = diskLabel(devs[0]); + result = diskLabel(devs[0]); } else { - menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); + menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook); if (!menu) { msgConfirm("No devices suitable for installation found!\n\n" "Please verify that your disk controller (and attached drives)\n" "were detected properly. This can be done by pressing the\n" "[Scroll Lock] key and using the Arrow keys to move back to\n" "the boot messages. Press [Scroll Lock] again to return."); - i = DITEM_FAILURE; + result = DITEM_FAILURE; } else { - i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; + result = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; free(menu); } } } - if (DITEM_STATUS(i) != DITEM_FAILURE) { + if (DITEM_STATUS(result) != DITEM_FAILURE) { if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); } - return i; + return result; } int -diskLabelCommit(dialogMenuItem *self) +diskLabelCommit(Device *dev) { char *cp; int i; /* Already done? */ if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) i = DITEM_SUCCESS; else if (!cp) { msgConfirm("You must assign disk labels before this option can be used."); i = DITEM_FAILURE; } /* The routine will guard against redundant writes, just as this one does */ - else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) + else if (DITEM_STATUS(diskPartitionWrite(dev)) != DITEM_SUCCESS) i = DITEM_FAILURE; - else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) + else if (DITEM_STATUS(installFilesystems(dev)) != DITEM_SUCCESS) i = DITEM_FAILURE; else { msgInfo("All filesystem information written successfully."); variable_set2(DISK_LABELLED, "written", 0); i = DITEM_SUCCESS; } return i; } /* See if we're already using a desired partition name */ static Boolean check_conflict(char *name) { int i; for (i = 0; label_chunk_info[i].c; i++) if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT || label_chunk_info[i].type == PART_EFI) && label_chunk_info[i].c->private_data && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) return TRUE; return FALSE; } /* How much space is in this FreeBSD slice? */ static daddr_t space_free(struct chunk *c) { struct chunk *c1; daddr_t sz = c->size; for (c1 = c->part; c1; c1 = c1->next) { if (c1->type != unused) sz -= c1->size; } if (sz < 0) msgFatal("Partitions are larger than actual chunk??"); return sz; } /* Snapshot the current situation into the displayed chunks structure */ static void -record_label_chunks(Device **devs, Device *dev) +record_label_chunks(Device *dev) { - int i, j, p; + int j, p; struct chunk *c1, *c2; - Disk *d; + Disk *d = (Disk *)dev->private; j = p = 0; /* First buzz through and pick up the FreeBSD slices */ - for (i = 0; devs[i]; i++) { - if ((dev && devs[i] != dev) || !devs[i]->enabled) - continue; - d = (Disk *)devs[i]->private; - if (!d->chunks) - msgFatal("No chunk list found for %s!", d->name); + if (!d->chunks) + msgFatal("No chunk list found for %s!", d->name); #ifdef __ia64__ - label_chunk_info[j].type = PART_SLICE; - label_chunk_info[j].c = d->chunks; - j++; + label_chunk_info[j].type = PART_SLICE; + label_chunk_info[j].c = d->chunks; + j++; #endif - /* Put the slice entries first */ - for (c1 = d->chunks->part; c1; c1 = c1->next) { - if (c1->type == freebsd) { - label_chunk_info[j].type = PART_SLICE; - label_chunk_info[j].c = c1; - ++j; - } + /* Put the slice entries first */ + for (c1 = d->chunks->part; c1; c1 = c1->next) { + if (c1->type == freebsd) { + label_chunk_info[j].type = PART_SLICE; + label_chunk_info[j].c = c1; + ++j; + } #ifdef __powerpc__ - if (c1->type == apple) { - label_chunk_info[j].type = PART_SLICE; - label_chunk_info[j].c = c1; - ++j; - } + if (c1->type == apple) { + label_chunk_info[j].type = PART_SLICE; + label_chunk_info[j].c = c1; + ++j; + } #endif - } } - /* Now run through again and get the FreeBSD partition entries */ - for (i = 0; devs[i]; i++) { - if (!devs[i]->enabled) - continue; - d = (Disk *)devs[i]->private; - /* Then buzz through and pick up the partitions */ - for (c1 = d->chunks->part; c1; c1 = c1->next) { - if (c1->type == freebsd) { - for (c2 = c1->part; c2; c2 = c2->next) { - if (c2->type == part) { - if (c2->subtype == FS_SWAP) - label_chunk_info[j].type = PART_SWAP; - else - label_chunk_info[j].type = PART_FILESYSTEM; - label_chunk_info[j].c = c2; - ++j; - } - } - } - else if (c1->type == fat) { - label_chunk_info[j].type = PART_FAT; - label_chunk_info[j].c = c1; - ++j; - } + /* Then buzz through and pick up the partitions */ + for (c1 = d->chunks->part; c1; c1 = c1->next) { + if (c1->type == freebsd) { + for (c2 = c1->part; c2; c2 = c2->next) { + if (c2->type == part) { + if (c2->subtype == FS_SWAP) + label_chunk_info[j].type = PART_SWAP; + else + label_chunk_info[j].type = PART_FILESYSTEM; + label_chunk_info[j].c = c2; + ++j; + } + } + } + else if (c1->type == fat) { + label_chunk_info[j].type = PART_FAT; + label_chunk_info[j].c = c1; + ++j; + } #ifdef __ia64__ - else if (c1->type == efi) { - label_chunk_info[j].type = PART_EFI; - label_chunk_info[j].c = c1; - ++j; - } - else if (c1->type == part) { - if (c1->subtype == FS_SWAP) - label_chunk_info[j].type = PART_SWAP; - else - label_chunk_info[j].type = PART_FILESYSTEM; - label_chunk_info[j].c = c1; - ++j; - } + else if (c1->type == efi) { + label_chunk_info[j].type = PART_EFI; + label_chunk_info[j].c = c1; + ++j; + } + else if (c1->type == part) { + if (c1->subtype == FS_SWAP) + label_chunk_info[j].type = PART_SWAP; + else + label_chunk_info[j].type = PART_FILESYSTEM; + label_chunk_info[j].c = c1; + ++j; + } #endif #ifdef __powerpc__ - else if (c1->type == apple) { - for (c2 = c1->part; c2; c2 = c2->next) { - if (c2->type == part) { - if (c2->subtype == FS_SWAP) - label_chunk_info[j].type = PART_SWAP; - else - label_chunk_info[j].type = PART_FILESYSTEM; - label_chunk_info[j].c = c2; - ++j; - } - } - } + else if (c1->type == apple) { + for (c2 = c1->part; c2; c2 = c2->next) { + if (c2->type == part) { + if (c2->subtype == FS_SWAP) + label_chunk_info[j].type = PART_SWAP; + else + label_chunk_info[j].type = PART_FILESYSTEM; + label_chunk_info[j].c = c2; + ++j; + } + } + } #endif - } } label_chunk_info[j].c = NULL; if (here >= j) { here = j ? j - 1 : 0; } } /* A new partition entry */ static PartInfo * new_part(PartType type, char *mpoint, Boolean newfs) { PartInfo *pi; if (!mpoint) mpoint = (type == PART_EFI) ? "/efi" : "/change_me"; pi = (PartInfo *)safe_malloc(sizeof(PartInfo)); sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX); pi->do_newfs = newfs; if (type == PART_EFI) { pi->newfs_type = NEWFS_MSDOS; } else { pi->newfs_type = NEWFS_UFS; strcpy(pi->newfs_data.newfs_ufs.user_options, ""); pi->newfs_data.newfs_ufs.acls = FALSE; pi->newfs_data.newfs_ufs.multilabel = FALSE; pi->newfs_data.newfs_ufs.softupdates = strcmp(mpoint, "/"); #ifdef PC98 pi->newfs_data.newfs_ufs.ufs1 = TRUE; #else pi->newfs_data.newfs_ufs.ufs1 = FALSE; #endif } return pi; } /* Get the mountpoint for a partition and save it away */ static PartInfo * get_mountpoint(PartType type, struct chunk *old) { char *val; PartInfo *tmp; Boolean newfs; if (old && old->private_data) tmp = old->private_data; else tmp = NULL; val = (tmp != NULL) ? tmp->mountpoint : (type == PART_EFI) ? "/efi" : NULL; val = msgGetInput(val, "Please specify a mount point for the partition"); if (!val || !*val) { if (!old) return NULL; else { free(old->private_data); old->private_data = NULL; } return NULL; } /* Is it just the same value? */ if (tmp && !strcmp(tmp->mountpoint, val)) return NULL; /* Did we use it already? */ if (check_conflict(val)) { msgConfirm("You already have a mount point for %s assigned!", val); return NULL; } /* Is it bogus? */ if (*val != '/') { msgConfirm("Mount point must start with a / character"); return NULL; } /* Is it going to be mounted on root? */ if (!strcmp(val, "/")) { if (old) old->flags |= CHUNK_IS_ROOT; } else if (old) old->flags &= ~CHUNK_IS_ROOT; newfs = TRUE; if (tmp) { newfs = tmp->do_newfs; safe_free(tmp); } val = string_skipwhite(string_prune(val)); tmp = new_part(type, val, newfs); if (old) { old->private_data = tmp; old->private_free = safe_free; } return tmp; } /* Get the type of the new partiton */ static PartType get_partition_type(void) { char selection[20]; int i; static unsigned char *fs_types[] = { #ifdef __ia64__ "EFI", "An EFI system partition", #endif "FS", "A file system", "Swap", "A swap partition.", }; WINDOW *w = savescr(); i = dialog_menu("Please choose a partition type", "If you want to use this partition for swap space, select Swap.\n" "If you want to put a filesystem on it, choose FS.", -1, -1, #ifdef __ia64__ 3, 3, #else 2, 2, #endif fs_types, selection, NULL, NULL); restorescr(w); if (!i) { #ifdef __ia64__ if (!strcmp(selection, "EFI")) return PART_EFI; #endif if (!strcmp(selection, "FS")) return PART_FILESYSTEM; else if (!strcmp(selection, "Swap")) return PART_SWAP; } return PART_NONE; } /* If the user wants a special newfs command for this, set it */ static void getNewfsCmd(PartInfo *p) { char buffer[NEWFS_CMD_ARGS_MAX]; char *val; switch (p->newfs_type) { case NEWFS_UFS: snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s %s %s %s", NEWFS_UFS_CMD, p->newfs_data.newfs_ufs.softupdates ? "-U" : "", p->newfs_data.newfs_ufs.ufs1 ? "-O1" : "-O2", p->newfs_data.newfs_ufs.user_options); break; case NEWFS_MSDOS: snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s", NEWFS_MSDOS_CMD); break; case NEWFS_CUSTOM: strcpy(buffer, p->newfs_data.newfs_custom.command); break; } val = msgGetInput(buffer, "Please enter the newfs command and options you'd like to use in\n" "creating this file system."); if (val != NULL) { p->newfs_type = NEWFS_CUSTOM; strlcpy(p->newfs_data.newfs_custom.command, val, NEWFS_CMD_ARGS_MAX); } } static void getNewfsOptionalArguments(PartInfo *p) { char buffer[NEWFS_CMD_ARGS_MAX]; char *val; /* Must be UFS, per argument checking in I/O routines. */ strlcpy(buffer, p->newfs_data.newfs_ufs.user_options, NEWFS_CMD_ARGS_MAX); val = msgGetInput(buffer, "Please enter any additional UFS newfs options you'd like to\n" "use in creating this file system."); if (val != NULL) strlcpy(p->newfs_data.newfs_ufs.user_options, val, NEWFS_CMD_ARGS_MAX); } #define MAX_MOUNT_NAME 9 #define PART_PART_COL 0 #define PART_MOUNT_COL 10 #define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) #define PART_NEWFS_COL (PART_SIZE_COL + 8) #define PART_OFF 38 #define TOTAL_AVAIL_LINES (10) #define PSLICE_SHOWABLE (4) /* stick this all up on the screen */ static void print_label_chunks(void) { int i, j, srow, prow, pcol; daddr_t sz; char clrmsg[80]; int ChunkPartStartRow; WINDOW *ChunkWin; /********************************************************/ /*** These values are for controling screen resources ***/ /*** Each label line holds up to 2 labels, so beware! ***/ /*** strategy will be to try to always make sure the ***/ /*** highlighted label is in the active display area. ***/ /********************************************************/ int pslice_max, label_max; int pslice_count, label_count, label_focus_found, pslice_focus_found; attrset(A_REVERSE); mvaddstr(0, 25, "FreeBSD Disklabel Editor"); attrset(A_NORMAL); /*** Count the number of parition slices ***/ pslice_count = 0; for (i = 0; label_chunk_info[i].c ; i++) { if (label_chunk_info[i].type == PART_SLICE) ++pslice_count; } pslice_max = pslice_count; /*** 4 line max for partition slices ***/ if (pslice_max > PSLICE_SHOWABLE) { pslice_max = PSLICE_SHOWABLE; } ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; /*** View partition slices modulo pslice_max ***/ label_max = TOTAL_AVAIL_LINES - pslice_max; for (i = 0; i < 2; i++) { mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); } srow = CHUNK_SLICE_START_ROW; prow = 0; pcol = 0; /*** these variables indicate that the focused item is shown currently ***/ label_focus_found = 0; pslice_focus_found = 0; label_count = 0; pslice_count = 0; mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); wclear(ChunkWin); /*** wrefresh(ChunkWin); ***/ for (i = 0; label_chunk_info[i].c; i++) { /* Is it a slice entry displayed at the top? */ if (label_chunk_info[i].type == PART_SLICE) { /*** This causes the new pslice to replace the previous display ***/ /*** focus must remain on the most recently active pslice ***/ if (pslice_count == pslice_max) { if (pslice_focus_found) { /*** This is where we can mark the more following ***/ attrset(A_BOLD); mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); attrset(A_NORMAL); continue; } else { /*** this is where we set the more previous ***/ attrset(A_BOLD); mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); attrset(A_NORMAL); pslice_count = 0; srow = CHUNK_SLICE_START_ROW; } } sz = space_free(label_chunk_info[i].c); if (i == here) attrset(ATTR_SELECTED); if (i == pslice_focus) pslice_focus_found = -1; if (label_chunk_info[i].c->type == whole) { if (sz >= 100 * ONE_GIG) mvprintw(srow++, 0, "Disk: %s\t\tFree: %jd blocks (%jdGB)", label_chunk_info[i].c->disk->name, (intmax_t)sz, (intmax_t)(sz / ONE_GIG)); else mvprintw(srow++, 0, "Disk: %s\t\tFree: %jd blocks (%jdMB)", label_chunk_info[i].c->disk->name, (intmax_t)sz, (intmax_t)(sz / ONE_MEG)); } else { if (sz >= 100 * ONE_GIG) mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %jd blocks (%jdGB)", label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, (intmax_t)sz, (intmax_t)(sz / ONE_GIG)); else mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %jd blocks (%jdMB)", label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, (intmax_t)sz, (intmax_t)(sz / ONE_MEG)); } attrset(A_NORMAL); clrtoeol(); move(0, 0); /*** refresh(); ***/ ++pslice_count; } /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ else { char onestr[PART_OFF], num[10], *mountpoint, newfs[12]; /* * We copy this into a blank-padded string so that it looks like * a solid bar in reverse-video */ memset(onestr, ' ', PART_OFF - 1); onestr[PART_OFF - 1] = '\0'; /*** Track how many labels have been displayed ***/ if (label_count == ((label_max - 1 ) * 2)) { if (label_focus_found) { continue; } else { label_count = 0; prow = 0; pcol = 0; } } /* Go for two columns if we've written one full columns worth */ /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ if (label_count == label_max - 1) { pcol = PART_OFF; prow = 0; } memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); /* If it's a filesystem, display the mountpoint */ if (label_chunk_info[i].c->private_data && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT || label_chunk_info[i].type == PART_EFI)) mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; else if (label_chunk_info[i].type == PART_SWAP) mountpoint = "swap"; else mountpoint = ""; /* Now display the newfs field */ if (label_chunk_info[i].type == PART_FAT) strcpy(newfs, "DOS"); #if defined(__ia64__) else if (label_chunk_info[i].type == PART_EFI) { strcpy(newfs, "EFI"); if (label_chunk_info[i].c->private_data) { strcat(newfs, " "); PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data; strcat(newfs, pi->do_newfs ? " Y" : " N"); } } #endif else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) { PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data; switch (pi->newfs_type) { case NEWFS_UFS: strcpy(newfs, NEWFS_UFS_STRING); if (pi->newfs_data.newfs_ufs.ufs1) strcat(newfs, "1"); else strcat(newfs, "2"); if (pi->newfs_data.newfs_ufs.softupdates) strcat(newfs, "+S"); else strcat(newfs, " "); break; case NEWFS_MSDOS: strcpy(newfs, "FAT"); break; case NEWFS_CUSTOM: strcpy(newfs, "CUST"); break; } strcat(newfs, pi->do_newfs ? " Y" : " N "); } else if (label_chunk_info[i].type == PART_SWAP) strcpy(newfs, "SWAP"); else strcpy(newfs, "*"); for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) onestr[PART_MOUNT_COL + j] = mountpoint[j]; if (label_chunk_info[i].c->size == 0) snprintf(num, 10, "%5dMB", 0); else if (label_chunk_info[i].c->size < (100 * ONE_GIG)) snprintf(num, 10, "%5jdMB", (intmax_t)label_chunk_info[i].c->size / ONE_MEG); else snprintf(num, 10, "%5jdGB", (intmax_t)label_chunk_info[i].c->size / ONE_GIG); memcpy(onestr + PART_SIZE_COL, num, strlen(num)); memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; if (i == label_focus) { label_focus_found = -1; wattrset(ChunkWin, A_BOLD); } if (i == here) wattrset(ChunkWin, ATTR_SELECTED); /*** lazy man's way of expensively padding this string ***/ while (strlen(onestr) < 37) strcat(onestr, " "); mvwaddstr(ChunkWin, prow, pcol, onestr); wattrset(ChunkWin, A_NORMAL); move(0, 0); ++prow; ++label_count; } } /*** this will erase all the extra stuff ***/ memset(clrmsg, ' ', 37); clrmsg[37] = '\0'; while (pslice_count < pslice_max) { mvprintw(srow++, 0, clrmsg); clrtoeol(); ++pslice_count; } while (label_count < (2 * (label_max - 1))) { mvwaddstr(ChunkWin, prow++, pcol, clrmsg); ++label_count; if (prow == (label_max - 1)) { prow = 0; pcol = PART_OFF; } } refresh(); wrefresh(ChunkWin); } static void print_command_summary(void) { mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); mvprintw(18, 56, "W = Write"); mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates Z = Custom Newfs"); mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge"); mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); move(0, 0); } static void clear_wins(void) { clear(); print_label_chunks(); } static int diskLabel(Device *dev) { daddr_t sz; int key = 0; Boolean labeling; char *msg = NULL; PartInfo *p, *oldp; PartType type; - Device **devs; WINDOW *w = savescr(); label_focus = 0; pslice_focus = 0; here = 0; - devs = deviceFind(NULL, DEVICE_TYPE_DISK); - if (!devs) { - msgConfirm("No disks found!"); - restorescr(w); - return DITEM_FAILURE; - } labeling = TRUE; keypad(stdscr, TRUE); - record_label_chunks(devs, dev); + record_label_chunks(dev); clear(); while (labeling) { char *cp; int rflags = DELCHUNK_NORMAL; print_label_chunks(); print_command_summary(); if (msg) { attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); clrtoeol(); beep(); msg = NULL; } else { move(23, 0); clrtoeol(); } refresh(); key = getch(); switch (toupper(key)) { - int i; static char _msg[40]; case '\014': /* ^L */ clear_wins(); break; case '\020': /* ^P */ case KEY_UP: case '-': if (here != 0) --here; else while (label_chunk_info[here + 1].c) ++here; break; case '\016': /* ^N */ case KEY_DOWN: case '+': case '\r': case '\n': if (label_chunk_info[here + 1].c) ++here; else here = 0; break; case KEY_HOME: here = 0; break; case KEY_END: while (label_chunk_info[here + 1].c) ++here; break; case KEY_F(1): case '?': systemDisplayHelp("partition"); clear_wins(); break; case '1': if (label_chunk_info[here].type == PART_FILESYSTEM) { PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); if ((pi != NULL) && (pi->newfs_type == NEWFS_UFS)) { pi->newfs_data.newfs_ufs.ufs1 = true; } else msg = MSG_NOT_APPLICABLE; } else msg = MSG_NOT_APPLICABLE; break; break; case '2': if (label_chunk_info[here].type == PART_FILESYSTEM) { PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); if ((pi != NULL) && (pi->newfs_type == NEWFS_UFS)) { pi->newfs_data.newfs_ufs.ufs1 = false; } else msg = MSG_NOT_APPLICABLE; } else msg = MSG_NOT_APPLICABLE; break; break; case 'A': if (label_chunk_info[here].type != PART_SLICE) { msg = "You can only do this in a disk slice (at top of screen)"; break; } /* * Generate standard partitions automatically. If we do not * have sufficient space we attempt to scale-down the size * of the partitions within certain bounds. */ { int perc; int req = 0; for (perc = 100; perc > 0; perc -= 5) { req = 0; /* reset for each loop */ - if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL) + if ((msg = try_auto_label(dev, perc, &req)) == NULL) break; } if (msg) { if (req) { msgConfirm(msg); clear_wins(); msg = NULL; } } } break; case 'C': if (label_chunk_info[here].type != PART_SLICE) { msg = "You can only do this in a master partition (see top of screen)"; break; } sz = space_free(label_chunk_info[here].c); if (sz <= FS_MIN_SIZE) { msg = "Not enough space to create an additional FreeBSD partition"; break; } else { char *val; daddr_t size; struct chunk *tmp; char osize[80]; u_long flags = 0; #ifdef __powerpc__ /* Always use the maximum size for apple partitions */ if (label_chunk_info[here].c->type == apple) size = sz; else { #endif sprintf(osize, "%jd", (intmax_t)sz); val = msgGetInput(osize, "Please specify the partition size in blocks or append a trailing G for\n" #ifdef __ia64__ "gigabytes, M for megabytes.\n" #else "gigabytes, M for megabytes, or C for cylinders.\n" #endif "%jd blocks (%jdMB) are free.", (intmax_t)sz, (intmax_t)sz / ONE_MEG); if (!val || (size = strtoimax(val, &cp, 0)) <= 0) { clear_wins(); break; } if (*cp) { if (toupper(*cp) == 'M') size *= ONE_MEG; else if (toupper(*cp) == 'G') size *= ONE_GIG; #ifndef __ia64__ else if (toupper(*cp) == 'C') size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); #endif } if (size <= FS_MIN_SIZE) { msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); clear_wins(); break; } #ifdef __powerpc__ } #endif type = get_partition_type(); if (type == PART_NONE) { clear_wins(); beep(); break; } if (type == PART_FILESYSTEM || type == PART_EFI) { if ((p = get_mountpoint(type, NULL)) == NULL) { clear_wins(); beep(); break; } else if (!strcmp(p->mountpoint, "/")) { if (type != PART_FILESYSTEM) { clear_wins(); beep(); break; } else flags |= CHUNK_IS_ROOT; } else flags &= ~CHUNK_IS_ROOT; } else p = NULL; if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) { msgConfirm("Warning: This is smaller than the recommended size for a\n" "root partition. For a variety of reasons, root\n" "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); } tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, size, #ifdef __ia64__ (type == PART_EFI) ? efi : part, (type == PART_EFI) ? 0 : (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, #else part, (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, #endif flags); if (!tmp) { msgConfirm("Unable to create the partition. Too big?"); clear_wins(); break; } #ifdef __alpha__ /* * SRM requires that the root partition is at the * begining of the disk and cannot boot otherwise. * Warn Alpha users if they are about to shoot themselves in * the foot in this way. * * Since partitions may not start precisely at offset 0 we * check for a "close to 0" instead. :-( */ if ((flags & CHUNK_IS_ROOT) && (tmp->offset > 1024)) { msgConfirm("Your root partition `a' does not seem to be the first\n" "partition. The Alpha's firmware can only boot from the\n" "first partition. So it is unlikely that your current\n" "disk layout will be bootable boot after installation.\n" "\n" "Please allocate the root partition before allocating\n" "any others.\n"); } #endif /* alpha */ tmp->private_data = p; tmp->private_free = safe_free; if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); - record_label_chunks(devs, dev); + record_label_chunks(dev); clear_wins(); /* This is where we assign focus to new label so it shows. */ { int i; label_focus = -1; for (i = 0; label_chunk_info[i].c; ++i) { if (label_chunk_info[i].c == tmp) { label_focus = i; break; } } if (label_focus == -1) label_focus = i - 1; } } break; case KEY_DC: case 'R': /* recover space (delete w/ recover) */ /* * Delete the partition w/ space recovery. */ rflags = DELCHUNK_RECOVER; /* fall through */ case 'D': /* delete */ if (label_chunk_info[here].type == PART_SLICE) { msg = MSG_NOT_APPLICABLE; break; } else if (label_chunk_info[here].type == PART_FAT) { msg = "Use the Disk Partition Editor to delete DOS partitions"; break; } Delete_Chunk2(label_chunk_info[here].c->disk, label_chunk_info[here].c, rflags); if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); - record_label_chunks(devs, dev); + record_label_chunks(dev); break; case 'M': /* mount */ switch(label_chunk_info[here].type) { case PART_SLICE: msg = MSG_NOT_APPLICABLE; break; case PART_SWAP: msg = "You don't need to specify a mountpoint for a swap partition."; break; case PART_FAT: case PART_EFI: case PART_FILESYSTEM: oldp = label_chunk_info[here].c->private_data; p = get_mountpoint(label_chunk_info[here].type, label_chunk_info[here].c); if (p) { if (!oldp) p->do_newfs = FALSE; if ((label_chunk_info[here].type == PART_FAT || label_chunk_info[here].type == PART_EFI) && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") || !strcmp(p->mountpoint, "/var"))) { msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); strcpy(p->mountpoint, "/bogus"); } } if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); - record_label_chunks(devs, dev); + record_label_chunks(dev); clear_wins(); break; default: msgFatal("Bogus partition under cursor???"); break; } break; case 'N': /* Set newfs options */ if (label_chunk_info[here].c->private_data && ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs) getNewfsOptionalArguments( label_chunk_info[here].c->private_data); else msg = MSG_NOT_APPLICABLE; clear_wins(); break; case 'S': /* Toggle soft updates flag */ if (label_chunk_info[here].type == PART_FILESYSTEM) { PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); if (pi != NULL && pi->newfs_type == NEWFS_UFS) pi->newfs_data.newfs_ufs.softupdates = !pi->newfs_data.newfs_ufs.softupdates; else msg = MSG_NOT_APPLICABLE; } else msg = MSG_NOT_APPLICABLE; break; case 'T': /* Toggle newfs state */ if ((label_chunk_info[here].type == PART_FILESYSTEM || label_chunk_info[here].type == PART_EFI) && (label_chunk_info[here].c->private_data)) { PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); if (!pi->do_newfs) label_chunk_info[here].c->flags |= CHUNK_NEWFS; else label_chunk_info[here].c->flags &= ~CHUNK_NEWFS; label_chunk_info[here].c->private_data = new_part(label_chunk_info[here].type, pi ? pi->mountpoint : NULL, pi ? !pi->do_newfs : TRUE); if (pi != NULL && pi->newfs_type == NEWFS_UFS) { PartInfo *pi_new = label_chunk_info[here].c->private_data; pi_new->newfs_data.newfs_ufs = pi->newfs_data.newfs_ufs; } safe_free(pi); label_chunk_info[here].c->private_free = safe_free; if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); } else msg = MSG_NOT_APPLICABLE; break; case 'U': clear(); if (!variable_cmp(DISK_LABELLED, "written")) { msgConfirm("You've already written out your changes -\n" "it's too late to undo!"); } else if (!msgNoYes("Are you SURE you want to Undo everything?")) { + Disk *d; + variable_unset(DISK_PARTITIONED); variable_unset(DISK_LABELLED); - for (i = 0; devs[i]; i++) { - Disk *d; - - if (!devs[i]->enabled) - continue; - else if ((d = Open_Disk(devs[i]->name)) != NULL) { - Free_Disk(devs[i]->private); - devs[i]->private = d; + if ((d = Open_Disk(dev->name)) != NULL) { + Free_Disk(dev->private); + dev->private = d; #ifdef WITH_SLICES - diskPartition(devs[i]); + diskPartition(dev); #endif - } } - record_label_chunks(devs, dev); + record_label_chunks(dev); } clear_wins(); break; case 'W': if (!variable_cmp(DISK_LABELLED, "written")) { msgConfirm("You've already written out your changes - if you\n" "wish to overwrite them, you'll have to restart\n" "%s first.", ProgName); } else if (!msgNoYes("WARNING: You are about to modify an EXISTING\n" "installation.\n\n" "Are you absolutely sure you want to continue?")) { variable_set2(DISK_LABELLED, "yes", 0); - diskLabelCommit(NULL); + diskLabelCommit(dev); } clear_wins(); break; case 'Z': /* Set newfs command line */ if (label_chunk_info[here].c->private_data && ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs) getNewfsCmd(label_chunk_info[here].c->private_data); else msg = MSG_NOT_APPLICABLE; clear_wins(); break; #ifndef __ia64__ case '|': if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n" "This is an entirely undocumented feature which you are not\n" "expected to understand!")) { - int i; - Device **devs; - dialog_clear(); end_dialog(); DialogActive = FALSE; - devs = deviceFind(NULL, DEVICE_TYPE_DISK); - if (!devs) { - msgConfirm("Can't find any disk devices!"); - break; + if (dev->private) { + slice_wizard(((Disk *)dev->private)); } - for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { - if (devs[i]->enabled) - slice_wizard(((Disk *)devs[i]->private)); - } if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); DialogActive = TRUE; - record_label_chunks(devs, dev); + record_label_chunks(dev); clear_wins(); } else msg = "A most prudent choice!"; break; #endif case '\033': /* ESC */ case 'Q': labeling = FALSE; break; default: beep(); sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); msg = _msg; break; } if (label_chunk_info[here].type == PART_SLICE) pslice_focus = here; else label_focus = here; } restorescr(w); return DITEM_SUCCESS; } static __inline daddr_t requested_part_size(char *varName, daddr_t nom, int def, int perc) { char *cp; daddr_t sz; if ((cp = variable_get(varName)) != NULL) sz = strtoimax(cp, NULL, 0); else sz = nom + (def - nom) * perc / 100; return(sz * ONE_MEG); } /* * Attempt to auto-label the disk. 'perc' (0-100) scales * the size of the various partitions within appropriate * bounds (NOMINAL through DEFAULT sizes). The procedure * succeeds of NULL is returned. A non-null return message * is either a failure-status message (*req == 0), or * a confirmation requestor (*req == 1). *req is 0 on * entry to this call. * * As a special exception to the usual sizing rules, /var is given * additional space equal to the amount of physical memory present * if perc == 100 in order to ensure that users with large hard drives * will have enough space to store a crashdump in /var/crash. * * We autolabel the following partitions: /, swap, /var, /tmp, /usr, * and /home. /home receives any extra left over disk space. */ static char * -try_auto_label(Device **devs, Device *dev, int perc, int *req) +try_auto_label(Device *dev, int perc, int *req) { daddr_t sz; Chunk *AutoHome, *AutoRoot, *AutoSwap; Chunk *AutoTmp, *AutoUsr, *AutoVar; #ifdef __ia64__ Chunk *AutoEfi; #endif int mib[2]; unsigned long physmem; size_t size; char *msg = NULL; sz = space_free(label_chunk_info[here].c); if (sz <= FS_MIN_SIZE) return("Not enough free space to create a new partition in the slice"); (void)checkLabels(FALSE); AutoHome = AutoRoot = AutoSwap = NULL; AutoTmp = AutoUsr = AutoVar = NULL; #ifdef __ia64__ AutoEfi = NULL; if (EfiChunk == NULL) { sz = 100 * ONE_MEG; AutoEfi = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, efi, 0, 0); if (AutoEfi == NULL) { *req = 1; msg = "Unable to create the EFI system partition. Too big?"; goto done; } AutoEfi->private_data = new_part(PART_EFI, "/efi", TRUE); AutoEfi->private_free = safe_free; AutoEfi->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } #endif if (RootChunk == NULL) { sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc); AutoRoot = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_BSDFFS, CHUNK_IS_ROOT | CHUNK_AUTO_SIZE); if (!AutoRoot) { *req = 1; msg = "Unable to create the root partition. Too big?"; goto done; } AutoRoot->private_data = new_part(PART_FILESYSTEM, "/", TRUE); AutoRoot->private_free = safe_free; AutoRoot->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } if (SwapChunk == NULL) { sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc); if (sz == 0) { daddr_t nom; daddr_t def; mib[0] = CTL_HW; mib[1] = HW_PHYSMEM; size = sizeof physmem; sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); def = 2 * (int)(physmem / 512); if (def < SWAP_MIN_SIZE * ONE_MEG) def = SWAP_MIN_SIZE * ONE_MEG; if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG) def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG; nom = (int)(physmem / 512) / 8; sz = nom + (def - nom) * perc / 100; } AutoSwap = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_SWAP, CHUNK_AUTO_SIZE); if (!AutoSwap) { *req = 1; msg = "Unable to create the swap partition. Too big?"; goto done; } AutoSwap->private_data = 0; AutoSwap->private_free = safe_free; - record_label_chunks(devs, dev); + record_label_chunks(dev); } if (VarChunk == NULL) { /* Work out how much extra space we want for a crash dump */ unsigned long crashdumpsz; mib[0] = CTL_HW; mib[1] = HW_PHYSMEM; size = sizeof(physmem); sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); if (perc == 100) crashdumpsz = physmem / 1048576; else crashdumpsz = 0; sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, \ VAR_DEFAULT_SIZE + crashdumpsz, perc); AutoVar = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_BSDFFS, CHUNK_AUTO_SIZE); if (!AutoVar) { *req = 1; msg = "Not enough free space for /var - you will need to\n" "partition your disk manually with a custom install!"; goto done; } AutoVar->private_data = new_part(PART_FILESYSTEM, "/var", TRUE); AutoVar->private_free = safe_free; AutoVar->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } if (TmpChunk == NULL && !variable_get(VAR_NO_TMP)) { sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc); AutoTmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_BSDFFS, CHUNK_AUTO_SIZE); if (!AutoTmp) { *req = 1; msg = "Not enough free space for /tmp - you will need to\n" "partition your disk manually with a custom install!"; goto done; } AutoTmp->private_data = new_part(PART_FILESYSTEM, "/tmp", TRUE); AutoTmp->private_free = safe_free; AutoTmp->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } if (UsrChunk == NULL && !variable_get(VAR_NO_USR)) { sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc); #if AUTO_HOME == 0 if (sz < space_free(label_chunk_info[here].c)) sz = space_free(label_chunk_info[here].c); #endif if (sz) { if (sz < (USR_MIN_SIZE * ONE_MEG)) { *req = 1; msg = "Not enough free space for /usr - you will need to\n" "partition your disk manually with a custom install!"; } AutoUsr = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_BSDFFS, CHUNK_AUTO_SIZE); if (!AutoUsr) { msg = "Unable to create the /usr partition. Not enough space?\n" "You will need to partition your disk manually with a custom install!"; goto done; } AutoUsr->private_data = new_part(PART_FILESYSTEM, "/usr", TRUE); AutoUsr->private_free = safe_free; AutoUsr->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } } #if AUTO_HOME == 1 if (HomeChunk == NULL && !variable_get(VAR_NO_HOME)) { sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc); if (sz < space_free(label_chunk_info[here].c)) sz = space_free(label_chunk_info[here].c); if (sz) { if (sz < (HOME_MIN_SIZE * ONE_MEG)) { *req = 1; msg = "Not enough free space for /home - you will need to\n" "partition your disk manually with a custom install!"; goto done; } AutoHome = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, sz, part, FS_BSDFFS, CHUNK_AUTO_SIZE); if (!AutoHome) { msg = "Unable to create the /home partition. Not enough space?\n" "You will need to partition your disk manually with a custom install!"; goto done; } AutoHome->private_data = new_part(PART_FILESYSTEM, "/home", TRUE); AutoHome->private_free = safe_free; AutoHome->flags |= CHUNK_NEWFS; - record_label_chunks(devs, dev); + record_label_chunks(dev); } } #endif /* At this point, we're reasonably "labelled" */ if (variable_cmp(DISK_LABELLED, "written")) variable_set2(DISK_LABELLED, "yes", 0); done: if (msg) { if (AutoRoot != NULL) Delete_Chunk(AutoRoot->disk, AutoRoot); if (AutoSwap != NULL) Delete_Chunk(AutoSwap->disk, AutoSwap); if (AutoVar != NULL) Delete_Chunk(AutoVar->disk, AutoVar); if (AutoTmp != NULL) Delete_Chunk(AutoTmp->disk, AutoTmp); if (AutoUsr != NULL) Delete_Chunk(AutoUsr->disk, AutoUsr); if (AutoHome != NULL) Delete_Chunk(AutoHome->disk, AutoHome); - record_label_chunks(devs, dev); + record_label_chunks(dev); } return(msg); } static int diskLabelNonInteractive(Device *dev) { char *cp; PartType type; PartInfo *p; u_long flags; int i, status; Device **devs; Disk *d; status = DITEM_SUCCESS; cp = variable_get(VAR_DISK); if (!cp) { msgConfirm("diskLabel: No disk selected - can't label automatically."); return DITEM_FAILURE; } devs = deviceFind(cp, DEVICE_TYPE_DISK); if (!devs) { msgConfirm("diskLabel: No disk device %s found!", cp); return DITEM_FAILURE; } if (dev) d = dev->private; else d = devs[0]->private; - record_label_chunks(devs, dev); + record_label_chunks(dev); for (i = 0; label_chunk_info[i].c; i++) { Chunk *c1 = label_chunk_info[i].c; if (label_chunk_info[i].type == PART_SLICE) { char name[512]; char typ[10], mpoint[50]; int entries; for (entries = 1;; entries++) { intmax_t sz; int soft = 0; snprintf(name, sizeof name, "%s-%d", c1->name, entries); if ((cp = variable_get(name)) == NULL) break; if (sscanf(cp, "%s %jd %s %d", typ, &sz, mpoint, &soft) < 3) { msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); status = DITEM_FAILURE; break; } else { Chunk *tmp; flags = 0; if (!strcmp(typ, "swap")) { type = PART_SWAP; strcpy(mpoint, "SWAP"); } else { type = PART_FILESYSTEM; if (!strcmp(mpoint, "/")) flags |= CHUNK_IS_ROOT; } if (!sz) sz = space_free(c1); if (sz > space_free(c1)) { msgConfirm("Not enough free space to create partition: %s", mpoint); status = DITEM_FAILURE; break; } if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { msgConfirm("Unable to create from partition spec: %s. Too big?", cp); status = DITEM_FAILURE; break; } else { PartInfo *pi; pi = tmp->private_data = new_part(PART_FILESYSTEM, mpoint, TRUE); tmp->private_free = safe_free; pi->newfs_data.newfs_ufs.softupdates = soft; } } } } else { /* Must be something we can set a mountpoint for */ cp = variable_get(c1->name); if (cp) { char mpoint[50], do_newfs[8]; Boolean newfs = FALSE; do_newfs[0] = '\0'; if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); status = DITEM_FAILURE; break; } newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; if (c1->private_data) { p = c1->private_data; p->do_newfs = newfs; strcpy(p->mountpoint, mpoint); } else { c1->private_data = new_part(PART_FILESYSTEM, mpoint, newfs); c1->private_free = safe_free; } if (!strcmp(mpoint, "/")) c1->flags |= CHUNK_IS_ROOT; else c1->flags &= ~CHUNK_IS_ROOT; } } } if (status == DITEM_SUCCESS) variable_set2(DISK_LABELLED, "yes", 0); return status; } Index: head/usr.sbin/sade/menus.c =================================================================== --- head/usr.sbin/sade/menus.c (revision 227938) +++ head/usr.sbin/sade/menus.c (revision 227939) @@ -1,116 +1,116 @@ /* * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif #include "sade.h" /* All the system menus go here. * * Hardcoded things like version number strings will disappear from * these menus just as soon as I add the code for doing inline variable * expansion. */ DMenu MenuDiskDevices = { - DMENU_CHECKLIST_TYPE | DMENU_SELECTION_RETURNS, + DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS, "Select Drive(s)", - "Please select the drive, or drives, on which you wish to perform\n" - "this operation. If you are attempting to install a boot partition\n" + "Please select the drive on which you wish to perform this\n" + "operation. If you are attempting to install a boot partition\n" "on a drive other than the first one or have multiple operating\n" "systems on your machine, you will have the option to install a boot\n" "manager later. To select a drive, use the arrow keys to move to it\n" - "and press [SPACE] or [ENTER]. To de-select it, press it again.\n\n" + "and press [SPACE] or [ENTER].\n\n" "Use [TAB] to get to the buttons and leave this menu.", "Press F1 for important information regarding disk geometry!", "drives", { { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0 } }, }; DMenu MenuMain = { DMENU_NORMAL_TYPE, "Disklabel and partitioning utility", "This is a utility for partitioning and/or labelling your disks.", "DISKUTIL", "main", { #ifdef WITH_SLICES { "1 Partition", "Managing disk partitions", NULL, diskPartitionEditor, NULL, NULL, 0, 0, 0, 0 }, #endif { "2 Label", "Label allocated disk partitions", NULL, diskLabelEditor, NULL, NULL, 0, 0, 0, 0 }, { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0 } }, }; #if defined(__i386__) || defined(__amd64__) #ifdef PC98 /* IPL type menu */ DMenu MenuIPLType = { DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS, "overwrite me", /* will be disk specific label */ "If you want a FreeBSD Boot Manager, select \"BootMgr\". If you would\n" "prefer your Boot Manager to remain untouched then select \"None\".\n\n", "Press F1 to read about drive setup", "drives", { { "BootMgr", "Install the FreeBSD Boot Manager", dmenuRadioCheck, dmenuSetValue, NULL, &BootMgr, 0, 0, 0, 0 }, { "None", "Leave the IPL untouched", dmenuRadioCheck, dmenuSetValue, NULL, &BootMgr, '(', '*', ')', 1 }, { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0 } }, }; #else /* MBR type menu */ DMenu MenuMBRType = { DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS, "overwrite me", /* will be disk specific label */ "FreeBSD comes with a boot manager that allows you to easily\n" "select between FreeBSD and any other operating systems on your machine\n" "at boot time. If you have more than one drive and want to boot\n" "from the second one, the boot manager will also make it possible\n" "to do so (limitations in the PC BIOS usually prevent this otherwise).\n" "If you have other operating systems installed and would like a choice when\n" "booting, choose \"BootMgr\". If you would prefer to keep your existing\n" "boot manager, select \"None\".\n\n", "", "drives", { { "Standard", "Install a standard MBR (non-interactive boot manager)", dmenuRadioCheck, dmenuSetValue, NULL, &BootMgr, '(', '*', ')', 1 }, { "BootMgr", "Install the FreeBSD boot manager", dmenuRadioCheck, dmenuSetValue, NULL, &BootMgr, '(', '*', ')', 0 }, { "None", "Do not install a boot manager", dmenuRadioCheck, dmenuSetValue, NULL, &BootMgr, '(', '*', ')', 2 }, { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0 } } }; #endif /* PC98 */ #endif /* __i386__ */ Index: head/usr.sbin/sade/sade.h =================================================================== --- head/usr.sbin/sade/sade.h (revision 227938) +++ head/usr.sbin/sade/sade.h (revision 227939) @@ -1,458 +1,455 @@ /* * Copyright (c) 1995 * Jordan Hubbard. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer, * verbatim and that no modifications are made prior to this * point in the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _SADE_H_INCLUDE #define _SADE_H_INCLUDE #include #include #include #include #include #include #include #include #include /*** Defines ***/ #if defined(__i386__) || defined(__amd64__) #define WITH_SYSCONS #define WITH_MICE #endif #if defined(__i386__) || defined(__amd64__) #define WITH_SLICES #endif #if defined(__i386__) #define WITH_LINUX #endif /* device limits */ #define DEV_NAME_MAX 128 /* The maximum length of a device name */ #define DEV_MAX 100 /* The maximum number of devices we'll deal with */ #define IO_ERROR -2 /* Status code for I/O error rather than normal EOF */ /* * I make some pretty gross assumptions about having a max of 50 chunks * total - 8 slices and 42 partitions. I can't easily display many more * than that on the screen at once! * * For 2.1 I'll revisit this and try to make it more dynamic, but since * this will catch 99.99% of all possible cases, I'm not too worried. */ #define MAX_CHUNKS 40 /* Internal environment variable names */ #define DISK_PARTITIONED "_diskPartitioned" #define DISK_LABELLED "_diskLabelled" #define DISK_SELECTED "_diskSelected" #define SYSTEM_STATE "_systemState" #define RUNNING_ON_ROOT "_runningOnRoot" /* Ones that can be tweaked from config files */ #define VAR_BLANKTIME "blanktime" #define VAR_BOOTMGR "bootManager" #define VAR_DEBUG "debug" #define VAR_DISK "disk" #define VAR_DISKINTERACTIVE "diskInteractive" #define VAR_DEDICATE_DISK "dedicateDisk" #define VAR_COMMAND "command" #define VAR_CONFIG_FILE "configFile" #define VAR_GEOMETRY "geometry" #define VAR_INSTALL_CFG "installConfig" #define VAR_INSTALL_ROOT "installRoot" #define VAR_LABEL "label" #define VAR_LABEL_COUNT "labelCount" #define VAR_NEWFS_ARGS "newfsArgs" #define VAR_NO_CONFIRM "noConfirm" #define VAR_NO_ERROR "noError" #define VAR_NO_WARN "noWarn" #define VAR_NO_USR "noUsr" #define VAR_NO_TMP "noTmp" #define VAR_NO_HOME "noHome" #define VAR_NONINTERACTIVE "nonInteractive" #define VAR_PARTITION "partition" #define VAR_RELNAME "releaseName" #define VAR_ROOT_SIZE "rootSize" #define VAR_SWAP_SIZE "swapSize" #define VAR_TAPE_BLOCKSIZE "tapeBlocksize" #define VAR_UFS_PATH "ufs" #define VAR_USR_SIZE "usrSize" #define VAR_VAR_SIZE "varSize" #define VAR_TMP_SIZE "tmpSize" #define VAR_TERM "TERM" #define VAR_CONSTERM "_consterm" #define DEFAULT_TAPE_BLOCKSIZE "20" /* One MB worth of blocks */ #define ONE_MEG 2048 #define ONE_GIG (ONE_MEG * 1024) /* Which selection attributes to use */ #define ATTR_SELECTED (ColorDisplay ? item_selected_attr : item_attr) #define ATTR_TITLE button_active_attr /* Handy strncpy() macro */ #define SAFE_STRCPY(to, from) sstrncpy((to), (from), sizeof (to) - 1) /*** Types ***/ typedef int Boolean; typedef struct disk Disk; typedef struct chunk Chunk; /* Bitfields for menu options */ #define DMENU_NORMAL_TYPE 0x1 /* Normal dialog menu */ #define DMENU_RADIO_TYPE 0x2 /* Radio dialog menu */ #define DMENU_CHECKLIST_TYPE 0x4 /* Multiple choice menu */ #define DMENU_SELECTION_RETURNS 0x8 /* Immediate return on item selection */ typedef struct _dmenu { int type; /* What sort of menu we are */ char *title; /* Our title */ char *prompt; /* Our prompt */ char *helpline; /* Line of help at bottom */ char *helpfile; /* Help file for "F1" */ dialogMenuItem items[]; /* Array of menu items */ } DMenu; /* An rc.conf variable */ typedef struct _variable { struct _variable *next; char *name; char *value; int dirty; } Variable; #define NO_ECHO_OBJ(type) ((type) | (DITEM_NO_ECHO << 16)) #define TYPE_OF_OBJ(type) ((type) & 0xff) #define ATTR_OF_OBJ(type) ((type) >> 16) /* A screen layout structure */ typedef struct _layout { int y; /* x & Y co-ordinates */ int x; int len; /* The size of the dialog on the screen */ int maxlen; /* How much the user can type in ... */ char *prompt; /* The string for the prompt */ char *help; /* The display for the help line */ void *var; /* The var to set when this changes */ int type; /* The type of the dialog to create */ void *obj; /* The obj pointer returned by libdialog */ } Layout; typedef enum { DEVICE_TYPE_NONE, DEVICE_TYPE_DISK, DEVICE_TYPE_DOS, DEVICE_TYPE_UFS, DEVICE_TYPE_ANY, } DeviceType; /* A "device" from sade's point of view */ typedef struct _device { char name[DEV_NAME_MAX]; char *description; char *devname; DeviceType type; - Boolean enabled; Boolean (*init)(struct _device *dev); FILE * (*get)(struct _device *dev, char *file, Boolean probe); void (*shutdown)(struct _device *dev); void *private; unsigned int flags; unsigned int volume; } Device; /* Some internal representations of partitions */ typedef enum { PART_NONE, PART_SLICE, PART_SWAP, PART_FILESYSTEM, PART_FAT, PART_EFI } PartType; #define NEWFS_UFS_CMD "newfs" #define NEWFS_MSDOS_CMD "newfs_msdos" enum newfs_type { NEWFS_UFS, NEWFS_MSDOS, NEWFS_CUSTOM }; #define NEWFS_UFS_STRING "UFS" #define NEWFS_MSDOS_STRING "FAT" #define NEWFS_CUSTOM_STRING "CST" /* The longest set of custom command line arguments we'll pass. */ #define NEWFS_CMD_ARGS_MAX 256 typedef struct _part_info { char mountpoint[FILENAME_MAX]; /* Is invocation of newfs desired? */ Boolean do_newfs; enum newfs_type newfs_type; union { struct { char user_options[NEWFS_CMD_ARGS_MAX]; Boolean acls; /* unused */ Boolean multilabel; /* unused */ Boolean softupdates; Boolean ufs1; } newfs_ufs; struct { /* unused */ } newfs_msdos; struct { char command[NEWFS_CMD_ARGS_MAX]; } newfs_custom; } newfs_data; } PartInfo; /* An option */ typedef struct _opt { char *name; char *desc; enum { OPT_IS_STRING, OPT_IS_INT, OPT_IS_FUNC, OPT_IS_VAR } type; void *data; void *aux; char *(*check)(void); } Option; typedef int (*commandFunc)(char *key, void *data); #define EXTRAS_FIELD_LEN 128 /*** Externs ***/ extern jmp_buf BailOut; /* Used to get the heck out */ extern int DebugFD; /* Where diagnostic output goes */ extern Boolean Fake; /* Don't actually modify anything - testing */ extern Boolean Restarting; /* Are we restarting sysinstall? */ extern Boolean SystemWasInstalled; /* Did we install it? */ extern Boolean RunningAsInit; /* Are we running stand-alone? */ extern Boolean DialogActive; /* Is the dialog() stuff up? */ extern Boolean ColorDisplay; /* Are we on a color display? */ extern Boolean OnVTY; /* On a syscons VTY? */ extern Variable *VarHead; /* The head of the variable chain */ extern int BootMgr; /* Which boot manager to use */ extern int StatusLine; /* Where to print our status messages */ #if defined(__i386__) || defined(__amd64__) #ifdef PC98 extern DMenu MenuIPLType; /* Type of IPL to write on the disk */ #else extern DMenu MenuMBRType; /* Type of MBR to write on the disk */ #endif #endif extern DMenu MenuMain; /* New main menu */ extern DMenu MenuDiskDevices; /* Disk type devices */ extern const char * StartName; /* Which name we were started as */ extern const char * ProgName; /* Program's proper name */ /* Important chunks. */ extern Chunk *HomeChunk; extern Chunk *RootChunk; extern Chunk *SwapChunk; extern Chunk *TmpChunk; extern Chunk *UsrChunk; extern Chunk *VarChunk; #ifdef __ia64__ extern Chunk *EfiChunk; #endif /* Stuff from libdialog which isn't properly declared outside */ extern void display_helpfile(void); extern void display_helpline(WINDOW *w, int y, int width); /*** Prototypes ***/ /* command.c */ extern void command_clear(void); extern void command_sort(void); extern void command_execute(void); extern void command_shell_add(char *key, const char *fmt, ...) __printflike(2, 3); extern void command_func_add(char *key, commandFunc func, void *data); /* devices.c */ -extern DMenu *deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)(dialogMenuItem *d), - int (*check)(dialogMenuItem *d)); +extern DMenu *deviceCreateMenu(DMenu *menu, DeviceType type, int (*hook)(dialogMenuItem *d)); extern void deviceGetAll(void); extern void deviceReset(void); extern void deviceRescan(void); extern Device **deviceFind(char *name, DeviceType type); extern Device **deviceFindDescr(char *name, char *desc, DeviceType class); extern int deviceCount(Device **devs); extern Device *new_device(char *name); -extern Device *deviceRegister(char *name, char *desc, char *devicename, DeviceType type, Boolean enabled, +extern Device *deviceRegister(char *name, char *desc, char *devicename, DeviceType type, Boolean (*init)(Device *mediadev), FILE * (*get)(Device *dev, char *file, Boolean probe), void (*shutDown)(Device *mediadev), void *private); extern Boolean dummyInit(Device *dev); extern FILE *dummyGet(Device *dev, char *dist, Boolean probe); extern void dummyShutdown(Device *dev); /* disks.c */ #ifdef WITH_SLICES extern void diskPartition(Device *dev); extern int diskPartitionEditor(dialogMenuItem *self); #endif -extern int diskPartitionWrite(dialogMenuItem *self); -extern int diskGetSelectCount(Device ***devs); +extern int diskPartitionWrite(Device *dev); /* dispatch.c */ extern int dispatchCommand(char *command); extern int dispatch_load_floppy(dialogMenuItem *self); extern int dispatch_load_file_int(int); extern int dispatch_load_file(dialogMenuItem *self); /* dmenu.c */ extern int dmenuDisplayFile(dialogMenuItem *tmp); extern int dmenuSubmenu(dialogMenuItem *tmp); extern int dmenuSystemCommand(dialogMenuItem *tmp); extern int dmenuSystemCommandBox(dialogMenuItem *tmp); extern int dmenuExit(dialogMenuItem *tmp); extern int dmenuISetVariable(dialogMenuItem *tmp); extern int dmenuSetVariable(dialogMenuItem *tmp); extern int dmenuSetVariables(dialogMenuItem *tmp); extern int dmenuToggleVariable(dialogMenuItem *tmp); extern int dmenuSetFlag(dialogMenuItem *tmp); extern int dmenuSetValue(dialogMenuItem *tmp); extern Boolean dmenuOpen(DMenu *menu, int *choice, int *bscroll, int *curr, int *max, Boolean buttons); extern Boolean dmenuOpenSimple(DMenu *menu, Boolean buttons); extern int dmenuVarCheck(dialogMenuItem *item); extern int dmenuVarsCheck(dialogMenuItem *item); extern int dmenuFlagCheck(dialogMenuItem *item); extern int dmenuRadioCheck(dialogMenuItem *item); /* dos.c */ extern Boolean mediaCloseDOS(Device *dev, FILE *fp); extern Boolean mediaInitDOS(Device *dev); extern FILE *mediaGetDOS(Device *dev, char *file, Boolean probe); extern void mediaShutdownDOS(Device *dev); /* globals.c */ extern void globalsInit(void); /* install.c */ extern Boolean checkLabels(Boolean whinge); extern int installCommit(dialogMenuItem *self); extern int installCustomCommit(dialogMenuItem *self); -extern int installFilesystems(dialogMenuItem *self); +extern int installFilesystems(Device *dev); extern int installVarDefaults(dialogMenuItem *self); extern void installEnvironment(void); extern Boolean copySelf(void); /* kget.c */ extern int kget(char *out); /* label.c */ extern int diskLabelEditor(dialogMenuItem *self); -extern int diskLabelCommit(dialogMenuItem *self); +extern int diskLabelCommit(Device *dev); /* misc.c */ extern Boolean file_readable(char *fname); extern Boolean directory_exists(const char *dirname); extern char *string_prune(char *str); extern char *string_skipwhite(char *str); extern void safe_free(void *ptr); extern void *safe_malloc(size_t size); extern int Mkdir(char *); extern int Mount(char *, void *data); extern WINDOW *savescr(void); extern void restorescr(WINDOW *w); extern char *sstrncpy(char *dst, const char *src, int size); /* msg.c */ extern Boolean isDebug(void); extern void msgInfo(const char *fmt, ...) __printf0like(1, 2); extern void msgYap(const char *fmt, ...) __printflike(1, 2); extern void msgWarn(const char *fmt, ...) __printflike(1, 2); extern void msgDebug(const char *fmt, ...) __printflike(1, 2); extern void msgError(const char *fmt, ...) __printflike(1, 2); extern void msgFatal(const char *fmt, ...) __printflike(1, 2); extern void msgConfirm(const char *fmt, ...) __printflike(1, 2); extern void msgNotify(const char *fmt, ...) __printflike(1, 2); extern void msgWeHaveOutput(const char *fmt, ...) __printflike(1, 2); extern int msgYesNo(const char *fmt, ...) __printflike(1, 2); extern int msgNoYes(const char *fmt, ...) __printflike(1, 2); extern char *msgGetInput(char *buf, const char *fmt, ...) __printflike(2, 3); extern int msgSimpleConfirm(const char *); extern int msgSimpleNotify(const char *); /* pccard.c */ extern void pccardInitialize(void); /* system.c */ extern void systemInitialize(int argc, char **argv); extern void systemShutdown(int status); extern int execExecute(char *cmd, char *name); extern int systemExecute(char *cmd); extern void systemSuspendDialog(void); extern void systemResumeDialog(void); extern int systemDisplayHelp(char *file); extern char *systemHelpFile(char *file, char *buf); extern void systemChangeFont(const u_char font[]); extern void systemChangeLang(char *lang); extern void systemChangeTerminal(char *color, const u_char c_termcap[], char *mono, const u_char m_termcap[]); extern void systemChangeScreenmap(const u_char newmap[]); extern int vsystem(const char *fmt, ...) __printflike(1, 2); /* termcap.c */ extern int set_termcap(void); /* variable.c */ extern void variable_set(char *var, int dirty); extern void variable_set2(char *name, char *value, int dirty); extern char *variable_get(char *var); extern int variable_cmp(char *var, char *value); extern void variable_unset(char *var); extern char *variable_get_value(char *var, char *prompt, int dirty); extern int variable_check(char *data); extern int variable_check2(char *data); extern int dump_variables(dialogMenuItem *self); extern void free_variables(void); extern void pvariable_set(char *var); extern char *pvariable_get(char *var); /* wizard.c */ extern void slice_wizard(Disk *d); /* * Macros. Please find a better place for us! */ #define DEVICE_INIT(d) ((d) != NULL ? (d)->init((d)) : (Boolean)0) #define DEVICE_GET(d, b, f) ((d) != NULL ? (d)->get((d), (b), (f)) : NULL) #define DEVICE_SHUTDOWN(d) ((d) != NULL ? (d)->shutdown((d)) : (void)0) #endif /* _SYSINSTALL_H_INCLUDE */