label.c revision 34543
18549Sjkh/* 28549Sjkh * The new sysinstall program. 38549Sjkh * 48549Sjkh * This is probably the last program in the `sysinstall' line - the next 58549Sjkh * generation being essentially a complete rewrite. 68549Sjkh * 734543Sjkh * $Id: label.c,v 1.81 1998/02/06 04:35:21 jkh Exp $ 88549Sjkh * 98549Sjkh * Copyright (c) 1995 108549Sjkh * Jordan Hubbard. All rights reserved. 118549Sjkh * 128549Sjkh * Redistribution and use in source and binary forms, with or without 138549Sjkh * modification, are permitted provided that the following conditions 148549Sjkh * are met: 158549Sjkh * 1. Redistributions of source code must retain the above copyright 168881Srgrimes * notice, this list of conditions and the following disclaimer, 178881Srgrimes * verbatim and that no modifications are made prior to this 188549Sjkh * point in the file. 198549Sjkh * 2. Redistributions in binary form must reproduce the above copyright 208549Sjkh * notice, this list of conditions and the following disclaimer in the 218549Sjkh * documentation and/or other materials provided with the distribution. 228549Sjkh * 238549Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 248549Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 258549Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 268549Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 278549Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 288549Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 298549Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 308549Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 318549Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 328549Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 338549Sjkh * SUCH DAMAGE. 348549Sjkh * 358549Sjkh */ 368549Sjkh 378549Sjkh#include "sysinstall.h" 388549Sjkh#include <ctype.h> 398549Sjkh#include <sys/disklabel.h> 4010882Speter#include <sys/param.h> 4110882Speter#include <sys/sysctl.h> 428549Sjkh 438549Sjkh/* 448549Sjkh * Everything to do with editing the contents of disk labels. 458549Sjkh */ 468549Sjkh 478549Sjkh/* A nice message we use a lot in the disklabel editor */ 488549Sjkh#define MSG_NOT_APPLICABLE "That option is not applicable here" 498549Sjkh 508549Sjkh/* Where to start printing the freebsd slices */ 518549Sjkh#define CHUNK_SLICE_START_ROW 2 528622Sjkh#define CHUNK_PART_START_ROW 11 538549Sjkh 548549Sjkh/* The smallest filesystem we're willing to create */ 558702Sjkh#define FS_MIN_SIZE ONE_MEG 568549Sjkh 578672Sjkh/* The smallest root filesystem we're willing to create */ 5812661Speter#define ROOT_MIN_SIZE 20 598549Sjkh 6012661Speter/* The smallest swap partition we want to create by default */ 6112661Speter#define SWAP_MIN_SIZE 16 6212661Speter 6312661Speter/* The smallest /usr partition we're willing to create by default */ 6412661Speter#define USR_MIN_SIZE 80 6512661Speter 6612661Speter/* The smallest /var partition we're willing to create by default */ 6712661Speter#define VAR_MIN_SIZE 30 6812661Speter 6915440Sjkh/* The bottom-most row we're allowed to scribble on */ 7029249Sjkh#define CHUNK_ROW_MAX 16 7115440Sjkh 7215440Sjkh 738549Sjkh/* All the chunks currently displayed on the screen */ 748549Sjkhstatic struct { 758549Sjkh struct chunk *c; 768549Sjkh PartType type; 778549Sjkh} label_chunk_info[MAX_CHUNKS + 1]; 788549Sjkhstatic int here; 798549Sjkh 8029249Sjkh/*** with this value we try to track the most recently added label ***/ 8129249Sjkhstatic int label_focus = 0, pslice_focus = 0; 8229249Sjkh 8330345Sjkhstatic int diskLabel(Device *dev); 8430345Sjkhstatic int diskLabelNonInteractive(Device *dev); 8512661Speter 8630345Sjkhstatic int 8730345SjkhlabelHook(dialogMenuItem *selected) 8830345Sjkh{ 8930345Sjkh Device **devs = NULL; 9030345Sjkh 9130345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 9230345Sjkh if (!devs) { 9330345Sjkh msgConfirm("Unable to find disk %s!", selected->prompt); 9430345Sjkh return DITEM_FAILURE; 9530345Sjkh } 9630345Sjkh /* Toggle enabled status? */ 9730345Sjkh if (!devs[0]->enabled) { 9830345Sjkh devs[0]->enabled = TRUE; 9930345Sjkh diskLabel(devs[0]); 10030345Sjkh } 10130345Sjkh else 10230345Sjkh devs[0]->enabled = FALSE; 10330345Sjkh return DITEM_SUCCESS | DITEM_RESTORE; 10430345Sjkh} 10530345Sjkh 10630345Sjkhstatic int 10730345SjkhlabelCheck(dialogMenuItem *selected) 10830345Sjkh{ 10930345Sjkh Device **devs = NULL; 11030345Sjkh 11130345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 11230345Sjkh if (!devs || devs[0]->enabled == FALSE) 11330345Sjkh return FALSE; 11430345Sjkh return TRUE; 11530345Sjkh} 11630345Sjkh 11712661Speterint 11815091SjkhdiskLabelEditor(dialogMenuItem *self) 11912661Speter{ 12030345Sjkh DMenu *menu; 12112661Speter Device **devs; 12230345Sjkh int i, cnt; 12312661Speter 12430345Sjkh i = 0; 12530345Sjkh cnt = diskGetSelectCount(&devs); 12630345Sjkh if (cnt == -1) { 12712661Speter msgConfirm("No disks found! Please verify that your disk controller is being\n" 12812661Speter "properly probed at boot time. See the Hardware Guide on the\n" 12912661Speter "Documentation menu for clues on diagnosing this type of problem."); 13015242Sjkh return DITEM_FAILURE; 13112661Speter } 13230345Sjkh else if (cnt) { 13330345Sjkh /* Some are already selected */ 13430381Sjkh if (variable_get(VAR_NONINTERACTIVE)) 13534543Sjkh i = diskLabelNonInteractive(NULL); 13630381Sjkh else 13734543Sjkh i = diskLabel(NULL); 13812661Speter } 13930345Sjkh else { 14030345Sjkh /* No disks are selected, fall-back case now */ 14130345Sjkh cnt = deviceCount(devs); 14230345Sjkh if (cnt == 1) { 14330345Sjkh devs[0]->enabled = TRUE; 14430345Sjkh if (variable_get(VAR_NONINTERACTIVE)) 14530345Sjkh i = diskLabelNonInteractive(devs[0]); 14630345Sjkh else 14730345Sjkh i = diskLabel(devs[0]); 14830345Sjkh } 14930345Sjkh else { 15030345Sjkh menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); 15130345Sjkh if (!menu) { 15230345Sjkh msgConfirm("No devices suitable for installation found!\n\n" 15330345Sjkh "Please verify that your disk controller (and attached drives)\n" 15430345Sjkh "were detected properly. This can be done by pressing the\n" 15530345Sjkh "[Scroll Lock] key and using the Arrow keys to move back to\n" 15630345Sjkh "the boot messages. Press [Scroll Lock] again to return."); 15730345Sjkh i = DITEM_FAILURE; 15830345Sjkh } 15930345Sjkh else { 16030345Sjkh i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 16130345Sjkh free(menu); 16230345Sjkh } 16330345Sjkh i |= DITEM_RESTORE; 16430345Sjkh } 16512661Speter } 16618744Sjkh if (DITEM_STATUS(i) != DITEM_FAILURE) { 16718744Sjkh char *cp; 16818744Sjkh 16918744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 17018744Sjkh variable_set2(DISK_LABELLED, "yes"); 17118744Sjkh } 17212661Speter return i; 17312661Speter} 17412661Speter 17512661Speterint 17615091SjkhdiskLabelCommit(dialogMenuItem *self) 17712661Speter{ 17812661Speter char *cp; 17912661Speter int i; 18012661Speter 18112661Speter /* Already done? */ 18217025Sjkh if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 18315242Sjkh i = DITEM_SUCCESS; 18412661Speter else if (!cp) { 18512661Speter msgConfirm("You must assign disk labels before this option can be used."); 18615242Sjkh i = DITEM_FAILURE; 18712661Speter } 18812661Speter /* The routine will guard against redundant writes, just as this one does */ 18915419Sjkh else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 19015242Sjkh i = DITEM_FAILURE; 19115419Sjkh else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 19215242Sjkh i = DITEM_FAILURE; 19312661Speter else { 19412661Speter msgInfo("All filesystem information written successfully."); 19512661Speter variable_set2(DISK_LABELLED, "written"); 19615242Sjkh i = DITEM_SUCCESS; 19712661Speter } 19812661Speter return i; 19912661Speter} 20012661Speter 2018549Sjkh/* See if we're already using a desired partition name */ 2028549Sjkhstatic Boolean 2038549Sjkhcheck_conflict(char *name) 2048549Sjkh{ 2058549Sjkh int i; 2068549Sjkh 2078751Sjkh for (i = 0; label_chunk_info[i].c; i++) 20823729Sjkh if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) 20923729Sjkh && label_chunk_info[i].c->private_data 21014793Sjoerg && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 2118549Sjkh return TRUE; 2128549Sjkh return FALSE; 2138549Sjkh} 2148549Sjkh 2158549Sjkh/* How much space is in this FreeBSD slice? */ 2168549Sjkhstatic int 2178549Sjkhspace_free(struct chunk *c) 2188549Sjkh{ 21912661Speter struct chunk *c1; 2208549Sjkh int sz = c->size; 2218549Sjkh 22212661Speter for (c1 = c->part; c1; c1 = c1->next) { 2238549Sjkh if (c1->type != unused) 2248549Sjkh sz -= c1->size; 2258549Sjkh } 2268549Sjkh if (sz < 0) 2278549Sjkh msgFatal("Partitions are larger than actual chunk??"); 2288549Sjkh return sz; 2298549Sjkh} 2308549Sjkh 2318549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 2328549Sjkhstatic void 23330345Sjkhrecord_label_chunks(Device **devs, Device *dev) 2348549Sjkh{ 2358549Sjkh int i, j, p; 2368549Sjkh struct chunk *c1, *c2; 2378556Sjkh Disk *d; 2388549Sjkh 2398549Sjkh j = p = 0; 2408556Sjkh /* First buzz through and pick up the FreeBSD slices */ 2418549Sjkh for (i = 0; devs[i]; i++) { 24230345Sjkh if ((dev && devs[i] != dev) || !devs[i]->enabled) 2438556Sjkh continue; 2448556Sjkh d = (Disk *)devs[i]->private; 2458556Sjkh if (!d->chunks) 2468556Sjkh msgFatal("No chunk list found for %s!", d->name); 2478549Sjkh 2488556Sjkh /* Put the slice entries first */ 2498556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2508549Sjkh if (c1->type == freebsd) { 2518549Sjkh label_chunk_info[j].type = PART_SLICE; 2528549Sjkh label_chunk_info[j].c = c1; 2538549Sjkh ++j; 2548549Sjkh } 2558549Sjkh } 2568549Sjkh } 25712661Speter 2588556Sjkh /* Now run through again and get the FreeBSD partition entries */ 2598556Sjkh for (i = 0; devs[i]; i++) { 2608556Sjkh if (!devs[i]->enabled) 2618556Sjkh continue; 2628556Sjkh d = (Disk *)devs[i]->private; 2638549Sjkh /* Then buzz through and pick up the partitions */ 2648556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2658549Sjkh if (c1->type == freebsd) { 2668549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 2678549Sjkh if (c2->type == part) { 2688549Sjkh if (c2->subtype == FS_SWAP) 2698549Sjkh label_chunk_info[j].type = PART_SWAP; 2708549Sjkh else 2718549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 2728549Sjkh label_chunk_info[j].c = c2; 2738549Sjkh ++j; 2748549Sjkh } 2758549Sjkh } 2768549Sjkh } 2778549Sjkh else if (c1->type == fat) { 2788549Sjkh label_chunk_info[j].type = PART_FAT; 2798549Sjkh label_chunk_info[j].c = c1; 2808702Sjkh ++j; 2818549Sjkh } 2828549Sjkh } 2838549Sjkh } 2848549Sjkh label_chunk_info[j].c = NULL; 28529249Sjkh if (here >= j) { 2868549Sjkh here = j ? j - 1 : 0; 28729249Sjkh } 2888549Sjkh} 2898549Sjkh 2908549Sjkh/* A new partition entry */ 2918549Sjkhstatic PartInfo * 2928665Sphknew_part(char *mpoint, Boolean newfs, u_long size) 2938549Sjkh{ 2948549Sjkh PartInfo *ret; 2958549Sjkh 2969202Srgrimes if (!mpoint) 2979202Srgrimes mpoint = "/change_me"; 2989202Srgrimes 2998549Sjkh ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 30020247Sjkh sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX); 30114335Sjkh strcpy(ret->newfs_cmd, "newfs -b 8192 -f 1024"); 3028666Sphk ret->newfs = newfs; 3038669Sphk if (!size) 30429249Sjkh return ret; 3058549Sjkh return ret; 3068549Sjkh} 3078549Sjkh 3088549Sjkh/* Get the mountpoint for a partition and save it away */ 30912661Speterstatic PartInfo * 3108589Sjkhget_mountpoint(struct chunk *old) 3118549Sjkh{ 3128549Sjkh char *val; 3138549Sjkh PartInfo *tmp; 3148549Sjkh 31514793Sjoerg if (old && old->private_data) 31614793Sjoerg tmp = old->private_data; 3178810Sjkh else 3188810Sjkh tmp = NULL; 31918619Sjkh if (!old) { 32018621Sjkh DialogX = 14; 32118621Sjkh DialogY = 16; 32218619Sjkh } 3238810Sjkh val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 32418619Sjkh DialogX = DialogY = 0; 3258764Sjkh if (!val || !*val) { 3268751Sjkh if (!old) 3278751Sjkh return NULL; 3288751Sjkh else { 32914793Sjoerg free(old->private_data); 33014793Sjoerg old->private_data = NULL; 3318751Sjkh } 3328669Sphk return NULL; 3338751Sjkh } 3348669Sphk 3358669Sphk /* Is it just the same value? */ 3368810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 3378669Sphk return NULL; 3388810Sjkh 3398810Sjkh /* Did we use it already? */ 3408669Sphk if (check_conflict(val)) { 3418669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 3428669Sphk return NULL; 3438549Sjkh } 3448810Sjkh 3458810Sjkh /* Is it bogus? */ 3468669Sphk if (*val != '/') { 3478669Sphk msgConfirm("Mount point must start with a / character"); 3488669Sphk return NULL; 3498669Sphk } 3508810Sjkh 3518810Sjkh /* Is it going to be mounted on root? */ 3528669Sphk if (!strcmp(val, "/")) { 3538669Sphk if (old) 3548669Sphk old->flags |= CHUNK_IS_ROOT; 3558810Sjkh } 3568810Sjkh else if (old) 3578669Sphk old->flags &= ~CHUNK_IS_ROOT; 3588810Sjkh 3598810Sjkh safe_free(tmp); 3608669Sphk tmp = new_part(val, TRUE, 0); 3618669Sphk if (old) { 36214793Sjoerg old->private_data = tmp; 3638669Sphk old->private_free = safe_free; 3648669Sphk } 3658669Sphk return tmp; 3668549Sjkh} 3678549Sjkh 3688549Sjkh/* Get the type of the new partiton */ 3698549Sjkhstatic PartType 3708549Sjkhget_partition_type(void) 3718549Sjkh{ 3728549Sjkh char selection[20]; 3738669Sphk int i; 3748669Sphk 3758549Sjkh static unsigned char *fs_types[] = { 3768549Sjkh "FS", 3778549Sjkh "A file system", 3788549Sjkh "Swap", 3798549Sjkh "A swap partition.", 3808549Sjkh }; 38118619Sjkh DialogX = 7; 38218621Sjkh DialogY = 8; 3838669Sphk i = dialog_menu("Please choose a partition type", 38412661Speter "If you want to use this partition for swap space, select Swap.\n" 38512661Speter "If you want to put a filesystem on it, choose FS.", 38612661Speter -1, -1, 2, 2, fs_types, selection, NULL, NULL); 38718619Sjkh DialogX = DialogY = 0; 3888669Sphk if (!i) { 3898549Sjkh if (!strcmp(selection, "FS")) 3908549Sjkh return PART_FILESYSTEM; 3918549Sjkh else if (!strcmp(selection, "Swap")) 3928549Sjkh return PART_SWAP; 3938549Sjkh } 3948549Sjkh return PART_NONE; 3958549Sjkh} 3968549Sjkh 3978549Sjkh/* If the user wants a special newfs command for this, set it */ 3988549Sjkhstatic void 3998549SjkhgetNewfsCmd(PartInfo *p) 4008549Sjkh{ 4018549Sjkh char *val; 4028549Sjkh 4038549Sjkh val = msgGetInput(p->newfs_cmd, 40412661Speter "Please enter the newfs command and options you'd like to use in\n" 40512661Speter "creating this file system."); 4068549Sjkh if (val) 40720247Sjkh sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 4088549Sjkh} 4098549Sjkh 4108549Sjkh#define MAX_MOUNT_NAME 12 4118549Sjkh 4128549Sjkh#define PART_PART_COL 0 4138549Sjkh#define PART_MOUNT_COL 8 4148549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 4158549Sjkh#define PART_NEWFS_COL (PART_SIZE_COL + 7) 4168549Sjkh#define PART_OFF 38 4178549Sjkh 41829249Sjkh#define TOTAL_AVAIL_LINES (10) 41929249Sjkh#define PSLICE_SHOWABLE (4) 42029249Sjkh 42129249Sjkh 4228549Sjkh/* stick this all up on the screen */ 4238549Sjkhstatic void 4248549Sjkhprint_label_chunks(void) 4258549Sjkh{ 42629249Sjkh int i, j, srow, prow, pcol; 42729249Sjkh int sz; 42829249Sjkh char clrmsg[80]; 42929633Sjkh int ChunkPartStartRow; 43029633Sjkh WINDOW *ChunkWin; 4318549Sjkh 43229249Sjkh /********************************************************/ 43329249Sjkh /*** These values are for controling screen resources ***/ 43429249Sjkh /*** Each label line holds up to 2 labels, so beware! ***/ 43529249Sjkh /*** strategy will be to try to always make sure the ***/ 43629249Sjkh /*** highlighted label is in the active display area. ***/ 43729249Sjkh /********************************************************/ 43829249Sjkh int pslice_max, label_max; 43929249Sjkh int pslice_count, label_count, label_focus_found, pslice_focus_found; 44029249Sjkh 4418549Sjkh attrset(A_REVERSE); 4428549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 4438549Sjkh attrset(A_NORMAL); 4448549Sjkh 44529633Sjkh /*** Count the number of parition slices ***/ 44629633Sjkh pslice_count = 0; 44729633Sjkh for (i = 0; label_chunk_info[i].c ; i++) { 44829633Sjkh if (label_chunk_info[i].type == PART_SLICE) 44929633Sjkh ++pslice_count; 45029633Sjkh } 45129633Sjkh pslice_max = pslice_count; 45229633Sjkh 45329633Sjkh /*** 4 line max for partition slices ***/ 45429633Sjkh if (pslice_max > PSLICE_SHOWABLE) { 45529633Sjkh pslice_max = PSLICE_SHOWABLE; 45629633Sjkh } 45729633Sjkh ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 45829633Sjkh 45929633Sjkh /*** View partition slices modulo pslice_max ***/ 46029633Sjkh label_max = TOTAL_AVAIL_LINES - pslice_max; 46129633Sjkh 4628549Sjkh for (i = 0; i < 2; i++) { 46315440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 46415440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 4658549Sjkh 46615440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 46715440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 4688549Sjkh 46915440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 47015440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 4718549Sjkh 47215440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 47315440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 4748549Sjkh } 4758549Sjkh srow = CHUNK_SLICE_START_ROW; 47615440Sjkh prow = 0; 4778549Sjkh pcol = 0; 4788549Sjkh 47929249Sjkh /*** these variables indicate that the focused item is shown currently ***/ 48029249Sjkh label_focus_found = 0; 48129249Sjkh pslice_focus_found = 0; 48229249Sjkh 48329249Sjkh label_count = 0; 48429249Sjkh pslice_count = 0; 48529249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 48629249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 48729249Sjkh 48829633Sjkh ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 48929633Sjkh 49029633Sjkh wclear(ChunkWin); 49129633Sjkh /*** wrefresh(ChunkWin); ***/ 49229633Sjkh 4938751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 4948549Sjkh /* Is it a slice entry displayed at the top? */ 4958549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 49629249Sjkh /*** This causes the new pslice to replace the previous display ***/ 49729249Sjkh /*** focus must remain on the most recently active pslice ***/ 49829249Sjkh if (pslice_count == pslice_max) { 49929249Sjkh if (pslice_focus_found) { 50029249Sjkh /*** This is where we can mark the more following ***/ 50129249Sjkh attrset(A_BOLD); 50229249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 50329249Sjkh attrset(A_NORMAL); 50429249Sjkh continue; 50529249Sjkh } 50629249Sjkh else { 50729249Sjkh /*** this is where we set the more previous ***/ 50829249Sjkh attrset(A_BOLD); 50929249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 51029249Sjkh attrset(A_NORMAL); 51129249Sjkh pslice_count = 0; 51229249Sjkh srow = CHUNK_SLICE_START_ROW; 51329249Sjkh } 51429249Sjkh } 51529249Sjkh 5168549Sjkh sz = space_free(label_chunk_info[i].c); 51715440Sjkh if (i == here) 51816208Sjkh attrset(ATTR_SELECTED); 51929249Sjkh if (i == pslice_focus) 52029249Sjkh pslice_focus_found = -1; 52129249Sjkh 52229249Sjkh mvprintw(srow++, 0, 52329249Sjkh "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 52429249Sjkh label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, 52529249Sjkh sz, (sz / ONE_MEG)); 52615440Sjkh attrset(A_NORMAL); 52715440Sjkh clrtoeol(); 52815440Sjkh move(0, 0); 52929633Sjkh /*** refresh(); ***/ 53029249Sjkh ++pslice_count; 5318549Sjkh } 53215440Sjkh /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 5338549Sjkh else { 5348549Sjkh char onestr[PART_OFF], num[10], *mountpoint, *newfs; 5358549Sjkh 5368549Sjkh /* 5378549Sjkh * We copy this into a blank-padded string so that it looks like 5388549Sjkh * a solid bar in reverse-video 5398549Sjkh */ 5408549Sjkh memset(onestr, ' ', PART_OFF - 1); 5418549Sjkh onestr[PART_OFF - 1] = '\0'; 54229249Sjkh 54329249Sjkh /*** Track how many labels have been displayed ***/ 54429249Sjkh if (label_count == ((label_max - 1 ) * 2)) { 54529249Sjkh if (label_focus_found) { 54629249Sjkh continue; 54729249Sjkh } 54829249Sjkh else { 54929249Sjkh label_count = 0; 55029249Sjkh prow = 0; 55129249Sjkh pcol = 0; 55229249Sjkh } 55329249Sjkh } 55429249Sjkh 55515440Sjkh /* Go for two columns if we've written one full columns worth */ 55629249Sjkh /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 55729249Sjkh if (label_count == label_max - 1) { 5588549Sjkh pcol = PART_OFF; 55915440Sjkh prow = 0; 5608549Sjkh } 5618705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 5628549Sjkh /* If it's a filesystem, display the mountpoint */ 56314793Sjoerg if (label_chunk_info[i].c->private_data 56410882Speter && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 56514793Sjoerg mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 56623529Sjkh else if (label_chunk_info[i].type == PART_SWAP) 56723529Sjkh mountpoint = "swap"; 56810882Speter else 56910882Speter mountpoint = "<none>"; 57010882Speter 57110882Speter /* Now display the newfs field */ 57210882Speter if (label_chunk_info[i].type == PART_FAT) 57310882Speter newfs = "DOS"; 57414793Sjoerg else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) 57514793Sjoerg newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N"; 57610882Speter else if (label_chunk_info[i].type == PART_SWAP) 57710882Speter newfs = "SWAP"; 57810882Speter else 5798549Sjkh newfs = "*"; 5808549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 5818549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 5828764Sjkh snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 5838549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 5848549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 5858549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 58629633Sjkh if (i == label_focus) { 58729633Sjkh label_focus_found = -1; 58829633Sjkh wattrset(ChunkWin, A_BOLD); 58929633Sjkh } 59015440Sjkh if (i == here) 59116208Sjkh wattrset(ChunkWin, ATTR_SELECTED); 59229249Sjkh 59329249Sjkh /*** lazy man's way of padding this string ***/ 59429249Sjkh while (strlen( onestr ) < 37) 59529249Sjkh strcat(onestr, " "); 59629249Sjkh 59715440Sjkh mvwaddstr(ChunkWin, prow, pcol, onestr); 59815440Sjkh wattrset(ChunkWin, A_NORMAL); 59915440Sjkh move(0, 0); 6008549Sjkh ++prow; 60129249Sjkh ++label_count; 6028549Sjkh } 6038549Sjkh } 60429249Sjkh 60529249Sjkh /*** this will erase all the extra stuff ***/ 60629249Sjkh memset(clrmsg, ' ', 37); 60729249Sjkh clrmsg[37] = '\0'; 60829249Sjkh 60929249Sjkh while (pslice_count < pslice_max) { 61029249Sjkh mvprintw(srow++, 0, clrmsg); 61129249Sjkh clrtoeol(); 61229249Sjkh ++pslice_count; 61329249Sjkh } 61429633Sjkh while (label_count < (2 * (label_max - 1))) { 61529633Sjkh mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 61629633Sjkh ++label_count; 61729633Sjkh if (prow == (label_max - 1)) { 61829633Sjkh prow = 0; 61929633Sjkh pcol = PART_OFF; 62029633Sjkh } 62129249Sjkh } 62229633Sjkh refresh(); 62329633Sjkh wrefresh(ChunkWin); 6248549Sjkh} 6258549Sjkh 6268549Sjkhstatic void 62718619Sjkhprint_command_summary(void) 6288549Sjkh{ 6298820Sjkh mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 63021971Sjkh mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 63115440Sjkh if (!RunningAsInit) 63230956Sobrien mvprintw(18, 49, "W = Write"); 63330956Sobrien mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish"); 63410882Speter mvprintw(20, 0, "A = Auto Defaults for all!"); 63515695Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 6368549Sjkh move(0, 0); 6378549Sjkh} 6388549Sjkh 63918619Sjkhstatic void 64018619Sjkhclear_wins(void) 64118619Sjkh{ 64229633Sjkh extern void print_label_chunks(); 64318619Sjkh clear(); 64429633Sjkh print_label_chunks(); 64518619Sjkh} 64618619Sjkh 64712661Speterstatic int 64830345SjkhdiskLabel(Device *dev) 6498549Sjkh{ 65018619Sjkh int sz, key = 0; 6518549Sjkh Boolean labeling; 6528549Sjkh char *msg = NULL; 6539202Srgrimes PartInfo *p, *oldp; 6548549Sjkh PartType type; 6558824Sjkh Device **devs; 6568549Sjkh 65729628Sjkh label_focus = 0; 65829628Sjkh pslice_focus = 0; 65929633Sjkh here = 0; 66030345Sjkh 66112661Speter devs = deviceFind(NULL, DEVICE_TYPE_DISK); 66212661Speter if (!devs) { 66312661Speter msgConfirm("No disks found!"); 66415242Sjkh return DITEM_FAILURE; 66512661Speter } 6668549Sjkh labeling = TRUE; 6678549Sjkh keypad(stdscr, TRUE); 66830345Sjkh record_label_chunks(devs, dev); 6698549Sjkh 67018619Sjkh clear(); 6718549Sjkh while (labeling) { 67218744Sjkh char *cp; 67318744Sjkh 6748549Sjkh print_label_chunks(); 67518619Sjkh print_command_summary(); 6768549Sjkh if (msg) { 67715695Sjkh attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 67812661Speter clrtoeol(); 6798549Sjkh beep(); 6808549Sjkh msg = NULL; 6818549Sjkh } 68215442Sjkh else { 68315442Sjkh move(23, 0); 68415442Sjkh clrtoeol(); 68515442Sjkh } 68618744Sjkh 68718619Sjkh refresh(); 68817397Sjkh key = getch(); 68917397Sjkh switch (toupper(key)) { 69015440Sjkh int i; 69117362Sjkh static char _msg[40]; 6928549Sjkh 6938751Sjkh case '\014': /* ^L */ 69418619Sjkh clear_wins(); 69518619Sjkh break; 6968751Sjkh 69721698Sjkh case '\020': /* ^P */ 6988549Sjkh case KEY_UP: 6998549Sjkh case '-': 7008549Sjkh if (here != 0) 7018549Sjkh --here; 7028751Sjkh else 7038751Sjkh while (label_chunk_info[here + 1].c) 7048751Sjkh ++here; 7058549Sjkh break; 7068549Sjkh 70721698Sjkh case '\016': /* ^N */ 7088549Sjkh case KEY_DOWN: 7098549Sjkh case '+': 7108549Sjkh case '\r': 7118549Sjkh case '\n': 7128751Sjkh if (label_chunk_info[here + 1].c) 7138549Sjkh ++here; 7148751Sjkh else 7158751Sjkh here = 0; 7168549Sjkh break; 7178549Sjkh 7188549Sjkh case KEY_HOME: 7198549Sjkh here = 0; 7208549Sjkh break; 7218549Sjkh 7228549Sjkh case KEY_END: 7238751Sjkh while (label_chunk_info[here + 1].c) 7248549Sjkh ++here; 7258549Sjkh break; 7268549Sjkh 7278549Sjkh case KEY_F(1): 7288549Sjkh case '?': 72912661Speter systemDisplayHelp("partition"); 73018619Sjkh clear_wins(); 7318549Sjkh break; 7328549Sjkh 73310882Speter case 'A': 73410882Speter if (label_chunk_info[here].type != PART_SLICE) { 73515440Sjkh msg = "You can only do this in a disk slice (at top of screen)"; 73610882Speter break; 73710882Speter } 73810882Speter sz = space_free(label_chunk_info[here].c); 73917362Sjkh if (sz <= FS_MIN_SIZE) 74015440Sjkh msg = "Not enough free space to create a new partition in the slice"; 74115440Sjkh else { 74215440Sjkh struct chunk *tmp; 74315440Sjkh int mib[2]; 74415440Sjkh int physmem; 74515440Sjkh size_t size, swsize; 74615440Sjkh char *cp; 74717362Sjkh Chunk *rootdev, *swapdev, *usrdev, *vardev; 74812661Speter 74917368Sjkh (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev); 75017362Sjkh if (!rootdev) { 75117362Sjkh cp = variable_get(VAR_ROOT_SIZE); 75217362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 75317362Sjkh (cp ? atoi(cp) : 32) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT); 75417362Sjkh if (!tmp) { 75517362Sjkh msgConfirm("Unable to create the root partition. Too big?"); 75618619Sjkh clear_wins(); 75717362Sjkh break; 75817362Sjkh } 75917362Sjkh tmp->private_data = new_part("/", TRUE, tmp->size); 76017362Sjkh tmp->private_free = safe_free; 76130345Sjkh record_label_chunks(devs, dev); 76215440Sjkh } 76317362Sjkh 76417362Sjkh if (!swapdev) { 76517362Sjkh cp = variable_get(VAR_SWAP_SIZE); 76617362Sjkh if (cp) 76717362Sjkh swsize = atoi(cp) * ONE_MEG; 76817362Sjkh else { 76917362Sjkh mib[0] = CTL_HW; 77017362Sjkh mib[1] = HW_PHYSMEM; 77117362Sjkh size = sizeof physmem; 77217362Sjkh sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 77317362Sjkh swsize = 16 * ONE_MEG + (physmem * 2 / 512); 77417362Sjkh } 77517362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 77617362Sjkh swsize, part, FS_SWAP, 0); 77717362Sjkh if (!tmp) { 77817362Sjkh msgConfirm("Unable to create the swap partition. Too big?"); 77918619Sjkh clear_wins(); 78017362Sjkh break; 78117362Sjkh } 78217362Sjkh tmp->private_data = 0; 78317362Sjkh tmp->private_free = safe_free; 78430345Sjkh record_label_chunks(devs, dev); 78515440Sjkh } 78617362Sjkh 78717362Sjkh if (!vardev) { 78817362Sjkh cp = variable_get(VAR_VAR_SIZE); 78917362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 79017362Sjkh (cp ? atoi(cp) : VAR_MIN_SIZE) * ONE_MEG, part, FS_BSDFFS, 0); 79117362Sjkh if (!tmp) { 79217362Sjkh msgConfirm("Less than %dMB free for /var - you will need to\n" 79317362Sjkh "partition your disk manually with a custom install!", 79417362Sjkh (cp ? atoi(cp) : VAR_MIN_SIZE)); 79518619Sjkh clear_wins(); 79617362Sjkh break; 79717362Sjkh } 79817362Sjkh tmp->private_data = new_part("/var", TRUE, tmp->size); 79917362Sjkh tmp->private_free = safe_free; 80030345Sjkh record_label_chunks(devs, dev); 80115440Sjkh } 80212661Speter 80317362Sjkh if (!usrdev) { 80417362Sjkh cp = variable_get(VAR_USR_SIZE); 80517362Sjkh if (cp) 80617362Sjkh sz = atoi(cp) * ONE_MEG; 80717362Sjkh else 80817362Sjkh sz = space_free(label_chunk_info[here].c); 80929501Sjkh if (sz) { 81029501Sjkh if (sz < (USR_MIN_SIZE * ONE_MEG)) { 81129501Sjkh msgConfirm("Less than %dMB free for /usr - you will need to\n" 81229501Sjkh "partition your disk manually with a custom install!", USR_MIN_SIZE); 81329501Sjkh clear_wins(); 81429501Sjkh break; 81529501Sjkh } 81617362Sjkh 81729501Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 81829501Sjkh label_chunk_info[here].c, 81929501Sjkh sz, part, FS_BSDFFS, 0); 82029501Sjkh if (!tmp) { 82129501Sjkh msgConfirm("Unable to create the /usr partition. Not enough space?\n" 82229501Sjkh "You will need to partition your disk manually with a custom install!"); 82329501Sjkh clear_wins(); 82429501Sjkh break; 82529501Sjkh } 82629501Sjkh tmp->private_data = new_part("/usr", TRUE, tmp->size); 82729501Sjkh tmp->private_free = safe_free; 82830345Sjkh record_label_chunks(devs, dev); 82917362Sjkh } 83015440Sjkh } 83115440Sjkh /* At this point, we're reasonably "labelled" */ 83218744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 83318744Sjkh variable_set2(DISK_LABELLED, "yes"); 83410882Speter } 83515440Sjkh break; 83610882Speter 8378549Sjkh case 'C': 8388549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 8398549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 8408549Sjkh break; 8418549Sjkh } 8428549Sjkh sz = space_free(label_chunk_info[here].c); 8438669Sphk if (sz <= FS_MIN_SIZE) { 84412661Speter msg = "Not enough space to create an additional FreeBSD partition"; 8458669Sphk break; 8468669Sphk } 84715440Sjkh else { 84818744Sjkh char *val; 8498702Sjkh int size; 8508702Sjkh struct chunk *tmp; 8518820Sjkh char osize[80]; 8528702Sjkh u_long flags = 0; 8538549Sjkh 8548820Sjkh sprintf(osize, "%d", sz); 85518619Sjkh DialogX = 3; 85618621Sjkh DialogY = 2; 85718619Sjkh val = msgGetInput(osize, 85818619Sjkh "Please specify the partition size in blocks or append a trailing M for\n" 85918619Sjkh "megabytes or C for cylinders. %d blocks (%dMB) are free.", 86018619Sjkh sz, sz / ONE_MEG); 86118619Sjkh DialogX = DialogY = 0; 86218619Sjkh if (!val || (size = strtol(val, &cp, 0)) <= 0) { 86318619Sjkh clear_wins(); 8648702Sjkh break; 86518619Sjkh } 8668549Sjkh 8678751Sjkh if (*cp) { 8688751Sjkh if (toupper(*cp) == 'M') 8698751Sjkh size *= ONE_MEG; 8708751Sjkh else if (toupper(*cp) == 'C') 8718751Sjkh size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 8728751Sjkh } 8738820Sjkh if (size <= FS_MIN_SIZE) { 8748820Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 87518619Sjkh clear_wins(); 8768820Sjkh break; 8778820Sjkh } 8788702Sjkh type = get_partition_type(); 87918619Sjkh if (type == PART_NONE) { 88018619Sjkh clear_wins(); 88118619Sjkh beep(); 8828669Sphk break; 88318619Sjkh } 8848669Sphk 8858702Sjkh if (type == PART_FILESYSTEM) { 88618619Sjkh if ((p = get_mountpoint(NULL)) == NULL) { 88718619Sjkh clear_wins(); 88818619Sjkh beep(); 8898702Sjkh break; 89018619Sjkh } 8918702Sjkh else if (!strcmp(p->mountpoint, "/")) 8928702Sjkh flags |= CHUNK_IS_ROOT; 8938702Sjkh else 8948702Sjkh flags &= ~CHUNK_IS_ROOT; 89518619Sjkh } 89618619Sjkh else 8978702Sjkh p = NULL; 8988702Sjkh 8998702Sjkh if ((flags & CHUNK_IS_ROOT)) { 9008702Sjkh if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 90112661Speter msgConfirm("This region cannot be used for your root partition as the\n" 90212661Speter "FreeBSD boot code cannot deal with a root partition created\n" 90312661Speter "in that location. Please choose another location or smaller\n" 90412661Speter "size for your root partition and try again!"); 90518619Sjkh clear_wins(); 9068702Sjkh break; 9078702Sjkh } 90812661Speter if (size < (ROOT_MIN_SIZE * ONE_MEG)) { 90912661Speter msgConfirm("Warning: This is smaller than the recommended size for a\n" 91012661Speter "root partition. For a variety of reasons, root\n" 91112661Speter "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 91212661Speter } 9138672Sjkh } 9148751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 9158702Sjkh label_chunk_info[here].c, 9168702Sjkh size, part, 9178702Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 9188702Sjkh flags); 9198702Sjkh if (!tmp) { 9208702Sjkh msgConfirm("Unable to create the partition. Too big?"); 92118619Sjkh clear_wins(); 9228672Sjkh break; 9238672Sjkh } 9248702Sjkh if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 92512661Speter msgConfirm("This region cannot be used for your root partition as it starts\n" 92612661Speter "or extends past the 1024'th cylinder mark and is thus a\n" 92712661Speter "poor location to boot from. Please choose another\n" 92812661Speter "location (or smaller size) for your root partition and try again!"); 9298751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, tmp); 93018619Sjkh clear_wins(); 9318669Sphk break; 9328702Sjkh } 9338702Sjkh if (type != PART_SWAP) { 9348669Sphk /* This is needed to tell the newfs -u about the size */ 93514793Sjoerg tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 9368669Sphk safe_free(p); 93715355Sjkh } 93815355Sjkh else 93914793Sjoerg tmp->private_data = p; 9408702Sjkh tmp->private_free = safe_free; 94118744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 94218744Sjkh variable_set2(DISK_LABELLED, "yes"); 94330345Sjkh record_label_chunks(devs, dev); 94418619Sjkh clear_wins(); 94529249Sjkh /*** This is where we assign focus to new label so it shows ***/ 94629249Sjkh { 94729249Sjkh int i; 94829249Sjkh label_focus = -1; 94929249Sjkh for (i = 0; label_chunk_info[i].c; ++i) { 95029249Sjkh if (label_chunk_info[i].c == tmp) { 95129249Sjkh label_focus = i; 95229249Sjkh break; 95329249Sjkh } 95429249Sjkh } 95529249Sjkh if (label_focus == -1) 95629249Sjkh label_focus = i - 1; 95729249Sjkh } 9588549Sjkh } 9598549Sjkh break; 9608549Sjkh 96117397Sjkh case KEY_DC: 9628549Sjkh case 'D': /* delete */ 9638549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 9648549Sjkh msg = MSG_NOT_APPLICABLE; 9658549Sjkh break; 9668549Sjkh } 9678549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 9688705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 9698549Sjkh break; 9708549Sjkh } 9718751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 97218744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 97318744Sjkh variable_set2(DISK_LABELLED, "yes"); 97430345Sjkh record_label_chunks(devs, dev); 9758549Sjkh break; 9768549Sjkh 9778549Sjkh case 'M': /* mount */ 9788549Sjkh switch(label_chunk_info[here].type) { 9798549Sjkh case PART_SLICE: 9808549Sjkh msg = MSG_NOT_APPLICABLE; 9818549Sjkh break; 9828549Sjkh 9838549Sjkh case PART_SWAP: 9848549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 9858549Sjkh break; 9868549Sjkh 9878556Sjkh case PART_FAT: 9888549Sjkh case PART_FILESYSTEM: 98914793Sjoerg oldp = label_chunk_info[here].c->private_data; 9908589Sjkh p = get_mountpoint(label_chunk_info[here].c); 9918549Sjkh if (p) { 9929202Srgrimes if (!oldp) 9939202Srgrimes p->newfs = FALSE; 9948722Sjkh if (label_chunk_info[here].type == PART_FAT 9958722Sjkh && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 9968722Sjkh || !strcmp(p->mountpoint, "/var"))) { 9978722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 9988722Sjkh strcpy(p->mountpoint, "/bogus"); 9998722Sjkh } 10008549Sjkh } 100118744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 100218744Sjkh variable_set2(DISK_LABELLED, "yes"); 100330345Sjkh record_label_chunks(devs, dev); 100418636Sjkh clear_wins(); 10058549Sjkh break; 10068549Sjkh 10078549Sjkh default: 10088549Sjkh msgFatal("Bogus partition under cursor???"); 10098549Sjkh break; 10108549Sjkh } 10118549Sjkh break; 10128549Sjkh 10138549Sjkh case 'N': /* Set newfs options */ 101414793Sjoerg if (label_chunk_info[here].c->private_data && 101514793Sjoerg ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 101614793Sjoerg getNewfsCmd(label_chunk_info[here].c->private_data); 10178549Sjkh else 10188549Sjkh msg = MSG_NOT_APPLICABLE; 101918636Sjkh clear_wins(); 10208549Sjkh break; 10218549Sjkh 10228549Sjkh case 'T': /* Toggle newfs state */ 10239202Srgrimes if (label_chunk_info[here].type == PART_FILESYSTEM) { 102423729Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 102523729Sjkh label_chunk_info[here].c->private_data = 102623729Sjkh new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 102723729Sjkh safe_free(pi); 102823729Sjkh label_chunk_info[here].c->private_free = safe_free; 102923729Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 103023729Sjkh variable_set2(DISK_LABELLED, "yes"); 103118619Sjkh } 10328549Sjkh else 10338549Sjkh msg = MSG_NOT_APPLICABLE; 10348549Sjkh break; 10358549Sjkh 10368820Sjkh case 'U': 103712661Speter clear(); 103818744Sjkh if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 103918744Sjkh msgConfirm("You've already written out your changes -\n" 104018744Sjkh "it's too late to undo!"); 104118744Sjkh } 104218744Sjkh else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 104318744Sjkh variable_unset(DISK_PARTITIONED); 104418744Sjkh variable_unset(DISK_LABELLED); 104518744Sjkh for (i = 0; devs[i]; i++) { 104618744Sjkh Disk *d; 104712661Speter 104818744Sjkh if (!devs[i]->enabled) 104918744Sjkh continue; 105018744Sjkh else if ((d = Open_Disk(devs[i]->name)) != NULL) { 105118744Sjkh Free_Disk(devs[i]->private); 105218744Sjkh devs[i]->private = d; 105330345Sjkh diskPartition(devs[i]); 105418744Sjkh } 10558824Sjkh } 105630345Sjkh record_label_chunks(devs, dev); 10578824Sjkh } 105818636Sjkh clear_wins(); 10598824Sjkh break; 10608820Sjkh 10618549Sjkh case 'W': 106218744Sjkh if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 106318744Sjkh msgConfirm("You've already written out your changes - if you\n" 106418744Sjkh "wish to overwrite them, you'll have to start this\n" 106518744Sjkh "procedure again from the beginning."); 106618744Sjkh } 106718744Sjkh else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 106818687Sjkh "installation. If you are installing FreeBSD for the first time\n" 106918687Sjkh "then you should simply type Q when you're finished here and your\n" 107018687Sjkh "changes will be committed in one batch automatically at the end of\n" 107118687Sjkh "these questions.\n\n" 107218687Sjkh "Are you absolutely sure you want to do this now?")) { 107312661Speter variable_set2(DISK_LABELLED, "yes"); 107412661Speter diskLabelCommit(NULL); 107512661Speter } 107618636Sjkh clear_wins(); 107710882Speter break; 107810882Speter 107910882Speter case '|': 108012661Speter if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 108112661Speter "This is an entirely undocumented feature which you are not\n" 108212661Speter "expected to understand!")) { 10838549Sjkh int i; 10848549Sjkh Device **devs; 10858549Sjkh 10868549Sjkh dialog_clear(); 10878549Sjkh end_dialog(); 10888549Sjkh DialogActive = FALSE; 10898549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 10908549Sjkh if (!devs) { 109112661Speter msgConfirm("Can't find any disk devices!"); 10928549Sjkh break; 10938549Sjkh } 10948668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 10958613Sjkh if (devs[i]->enabled) 10968613Sjkh slice_wizard(((Disk *)devs[i]->private)); 10978613Sjkh } 109818744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 109918744Sjkh variable_set2(DISK_LABELLED, "yes"); 11008665Sphk DialogActive = TRUE; 110130345Sjkh record_label_chunks(devs, dev); 110218636Sjkh clear_wins(); 11038549Sjkh } 11048549Sjkh else 11058549Sjkh msg = "A most prudent choice!"; 11068549Sjkh break; 11078549Sjkh 110821698Sjkh case '\033': /* ESC */ 11099202Srgrimes case 'Q': 11108549Sjkh labeling = FALSE; 11118549Sjkh break; 11128549Sjkh 11138549Sjkh default: 11148549Sjkh beep(); 111517362Sjkh sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 111617362Sjkh msg = _msg; 11178549Sjkh break; 11188549Sjkh } 111929633Sjkh if (label_chunk_info[here].type == PART_SLICE) 112029633Sjkh pslice_focus = here; 112129633Sjkh else 112229633Sjkh label_focus = here; 11238549Sjkh } 112417362Sjkh return DITEM_SUCCESS | DITEM_RESTORE; 11258549Sjkh} 112626456Sjkh 112726456Sjkhstatic int 112830345SjkhdiskLabelNonInteractive(Device *dev) 112926456Sjkh{ 113026456Sjkh char *cp; 113126456Sjkh PartType type; 113226456Sjkh PartInfo *p; 113326456Sjkh u_long flags = 0; 113426456Sjkh int i, status; 113526456Sjkh Device **devs; 113626456Sjkh Disk *d; 113726456Sjkh 113826456Sjkh status = DITEM_SUCCESS; 113930345Sjkh 114026456Sjkh cp = variable_get(VAR_DISK); 114126456Sjkh if (!cp) { 114226456Sjkh dialog_clear(); 114326456Sjkh msgConfirm("diskLabel: No disk selected - can't label automatically."); 114426456Sjkh return DITEM_FAILURE; 114526456Sjkh } 114626456Sjkh devs = deviceFind(cp, DEVICE_TYPE_DISK); 114726456Sjkh if (!devs) { 114826456Sjkh msgConfirm("diskLabel: No disk device %s found!", cp); 114926456Sjkh return DITEM_FAILURE; 115026456Sjkh } 115130345Sjkh if (dev) 115230345Sjkh d = dev->private; 115330345Sjkh else 115430345Sjkh d = devs[0]->private; 115530345Sjkh record_label_chunks(devs, dev); 115626456Sjkh for (i = 0; label_chunk_info[i].c; i++) { 115726456Sjkh Chunk *c1 = label_chunk_info[i].c; 115826456Sjkh 115926456Sjkh if (label_chunk_info[i].type == PART_SLICE) { 116028075Sjkh char name[512]; 116128075Sjkh int entries = 1; 116226456Sjkh 116328075Sjkh while (entries) { 116428075Sjkh snprintf(name, sizeof name, "%s-%d", c1->name, entries); 116528075Sjkh if ((cp = variable_get(name)) != NULL) { 116628075Sjkh int sz; 116728075Sjkh char typ[10], mpoint[50]; 116826456Sjkh 116928075Sjkh if (sscanf(cp, "%s %d %s", typ, &sz, mpoint) != 3) { 117028075Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 117126456Sjkh status = DITEM_FAILURE; 117226456Sjkh continue; 117326456Sjkh } 117426456Sjkh else { 117528075Sjkh Chunk *tmp; 117628075Sjkh 117728075Sjkh if (!strcmp(typ, "swap")) { 117828075Sjkh type = PART_SWAP; 117928075Sjkh strcpy(mpoint, "SWAP"); 118028075Sjkh } 118128075Sjkh else { 118228075Sjkh type = PART_FILESYSTEM; 118328075Sjkh if (!strcmp(mpoint, "/")) 118428075Sjkh flags |= CHUNK_IS_ROOT; 118533132Sjkh else 118633132Sjkh flags &= ~CHUNK_IS_ROOT; 118728075Sjkh } 118828075Sjkh if (!sz) 118928075Sjkh sz = space_free(c1); 119028075Sjkh if (sz > space_free(c1)) { 119128075Sjkh msgConfirm("Not enough free space to create partition: %s", mpoint); 119228075Sjkh status = DITEM_FAILURE; 119328075Sjkh continue; 119428075Sjkh } 119528075Sjkh if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 119628075Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 119728075Sjkh msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 119828075Sjkh status = DITEM_FAILURE; 119928075Sjkh break; 120028075Sjkh } 120128075Sjkh else { 120228075Sjkh tmp->private_data = new_part(mpoint, TRUE, sz); 120328075Sjkh tmp->private_free = safe_free; 120428075Sjkh status = DITEM_SUCCESS; 120528075Sjkh } 120626456Sjkh } 120728075Sjkh entries++; 120826456Sjkh } 120928075Sjkh else { 121028075Sjkh /* No more matches, leave the loop */ 121128075Sjkh entries = 0; 121228075Sjkh } 121326456Sjkh } 121426456Sjkh } 121526456Sjkh else { 121628075Sjkh /* Must be something we can set a mountpoint for */ 121726456Sjkh cp = variable_get(c1->name); 121826456Sjkh if (cp) { 121928075Sjkh char mpoint[50], do_newfs[8]; 122026456Sjkh Boolean newfs = FALSE; 122126456Sjkh 122228075Sjkh do_newfs[0] = '\0'; 122328075Sjkh if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 122426456Sjkh dialog_clear(); 122526456Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 122626456Sjkh status = DITEM_FAILURE; 122726456Sjkh continue; 122826456Sjkh } 122928075Sjkh newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 123026456Sjkh if (c1->private_data) { 123126456Sjkh p = c1->private_data; 123226456Sjkh p->newfs = newfs; 123326456Sjkh strcpy(p->mountpoint, mpoint); 123426456Sjkh } 123526456Sjkh else { 123626456Sjkh c1->private_data = new_part(mpoint, newfs, 0); 123726456Sjkh c1->private_free = safe_free; 123826456Sjkh } 123926456Sjkh if (!strcmp(mpoint, "/")) 124026456Sjkh c1->flags |= CHUNK_IS_ROOT; 124126456Sjkh else 124226456Sjkh c1->flags &= ~CHUNK_IS_ROOT; 124326456Sjkh } 124426456Sjkh } 124526456Sjkh } 124626456Sjkh if (status == DITEM_SUCCESS) 124726456Sjkh variable_set2(DISK_LABELLED, "yes"); 124826456Sjkh return status; 124926456Sjkh} 1250