label.c revision 76299
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 * 750479Speter * $FreeBSD: head/usr.sbin/sysinstall/label.c 76299 2001-05-06 02:52:45Z jkh $ 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 */ 5844601Sjkh#ifdef __alpha__ 5945127Sjkh#define ROOT_MIN_SIZE 40 6044601Sjkh#else 6145127Sjkh#define ROOT_MIN_SIZE 30 6244601Sjkh#endif 638549Sjkh 6444601Sjkh/* The default root filesystem size */ 6544601Sjkh#ifdef __alpha__ 6675250Sobrien#define ROOT_DEFAULT_SIZE 120 6772122Sobrien#else 6872124Sobrien#define ROOT_DEFAULT_SIZE 100 6944601Sjkh#endif 7044601Sjkh 7112661Speter/* The smallest swap partition we want to create by default */ 7254716Sjkh#define SWAP_MIN_SIZE 32 7312661Speter 7412661Speter/* The smallest /usr partition we're willing to create by default */ 7512661Speter#define USR_MIN_SIZE 80 7612661Speter 7712661Speter/* The smallest /var partition we're willing to create by default */ 7845127Sjkh#define VAR_MIN_SIZE 20 7912661Speter 8015440Sjkh/* The bottom-most row we're allowed to scribble on */ 8129249Sjkh#define CHUNK_ROW_MAX 16 8215440Sjkh 8315440Sjkh 848549Sjkh/* All the chunks currently displayed on the screen */ 858549Sjkhstatic struct { 868549Sjkh struct chunk *c; 878549Sjkh PartType type; 888549Sjkh} label_chunk_info[MAX_CHUNKS + 1]; 898549Sjkhstatic int here; 908549Sjkh 9129249Sjkh/*** with this value we try to track the most recently added label ***/ 9229249Sjkhstatic int label_focus = 0, pslice_focus = 0; 9329249Sjkh 9430345Sjkhstatic int diskLabel(Device *dev); 9530345Sjkhstatic int diskLabelNonInteractive(Device *dev); 9612661Speter 9730345Sjkhstatic int 9830345SjkhlabelHook(dialogMenuItem *selected) 9930345Sjkh{ 10030345Sjkh Device **devs = NULL; 10130345Sjkh 10230345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 10330345Sjkh if (!devs) { 10430345Sjkh msgConfirm("Unable to find disk %s!", selected->prompt); 10530345Sjkh return DITEM_FAILURE; 10630345Sjkh } 10730345Sjkh /* Toggle enabled status? */ 10830345Sjkh if (!devs[0]->enabled) { 10930345Sjkh devs[0]->enabled = TRUE; 11030345Sjkh diskLabel(devs[0]); 11130345Sjkh } 11230345Sjkh else 11330345Sjkh devs[0]->enabled = FALSE; 11454587Sjkh return DITEM_SUCCESS; 11530345Sjkh} 11630345Sjkh 11730345Sjkhstatic int 11830345SjkhlabelCheck(dialogMenuItem *selected) 11930345Sjkh{ 12030345Sjkh Device **devs = NULL; 12130345Sjkh 12230345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 12330345Sjkh if (!devs || devs[0]->enabled == FALSE) 12430345Sjkh return FALSE; 12530345Sjkh return TRUE; 12630345Sjkh} 12730345Sjkh 12812661Speterint 12915091SjkhdiskLabelEditor(dialogMenuItem *self) 13012661Speter{ 13130345Sjkh DMenu *menu; 13212661Speter Device **devs; 13330345Sjkh int i, cnt; 13412661Speter 13530345Sjkh i = 0; 13630345Sjkh cnt = diskGetSelectCount(&devs); 13730345Sjkh if (cnt == -1) { 13812661Speter msgConfirm("No disks found! Please verify that your disk controller is being\n" 13912661Speter "properly probed at boot time. See the Hardware Guide on the\n" 14012661Speter "Documentation menu for clues on diagnosing this type of problem."); 14115242Sjkh return DITEM_FAILURE; 14212661Speter } 14330345Sjkh else if (cnt) { 14430345Sjkh /* Some are already selected */ 14530381Sjkh if (variable_get(VAR_NONINTERACTIVE)) 14634543Sjkh i = diskLabelNonInteractive(NULL); 14730381Sjkh else 14834543Sjkh i = diskLabel(NULL); 14912661Speter } 15030345Sjkh else { 15130345Sjkh /* No disks are selected, fall-back case now */ 15230345Sjkh cnt = deviceCount(devs); 15330345Sjkh if (cnt == 1) { 15430345Sjkh devs[0]->enabled = TRUE; 15530345Sjkh if (variable_get(VAR_NONINTERACTIVE)) 15630345Sjkh i = diskLabelNonInteractive(devs[0]); 15730345Sjkh else 15830345Sjkh i = diskLabel(devs[0]); 15930345Sjkh } 16030345Sjkh else { 16130345Sjkh menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); 16230345Sjkh if (!menu) { 16330345Sjkh msgConfirm("No devices suitable for installation found!\n\n" 16430345Sjkh "Please verify that your disk controller (and attached drives)\n" 16530345Sjkh "were detected properly. This can be done by pressing the\n" 16630345Sjkh "[Scroll Lock] key and using the Arrow keys to move back to\n" 16730345Sjkh "the boot messages. Press [Scroll Lock] again to return."); 16830345Sjkh i = DITEM_FAILURE; 16930345Sjkh } 17030345Sjkh else { 17130345Sjkh i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 17230345Sjkh free(menu); 17330345Sjkh } 17430345Sjkh } 17512661Speter } 17618744Sjkh if (DITEM_STATUS(i) != DITEM_FAILURE) { 17774156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 17843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 17918744Sjkh } 18012661Speter return i; 18112661Speter} 18212661Speter 18312661Speterint 18415091SjkhdiskLabelCommit(dialogMenuItem *self) 18512661Speter{ 18612661Speter char *cp; 18712661Speter int i; 18812661Speter 18912661Speter /* Already done? */ 19017025Sjkh if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 19115242Sjkh i = DITEM_SUCCESS; 19212661Speter else if (!cp) { 19312661Speter msgConfirm("You must assign disk labels before this option can be used."); 19415242Sjkh i = DITEM_FAILURE; 19512661Speter } 19612661Speter /* The routine will guard against redundant writes, just as this one does */ 19715419Sjkh else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 19815242Sjkh i = DITEM_FAILURE; 19915419Sjkh else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 20015242Sjkh i = DITEM_FAILURE; 20112661Speter else { 20212661Speter msgInfo("All filesystem information written successfully."); 20343685Sjkh variable_set2(DISK_LABELLED, "written", 0); 20415242Sjkh i = DITEM_SUCCESS; 20512661Speter } 20612661Speter return i; 20712661Speter} 20812661Speter 2098549Sjkh/* See if we're already using a desired partition name */ 2108549Sjkhstatic Boolean 2118549Sjkhcheck_conflict(char *name) 2128549Sjkh{ 2138549Sjkh int i; 2148549Sjkh 2158751Sjkh for (i = 0; label_chunk_info[i].c; i++) 21623729Sjkh if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) 21723729Sjkh && label_chunk_info[i].c->private_data 21814793Sjoerg && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 2198549Sjkh return TRUE; 2208549Sjkh return FALSE; 2218549Sjkh} 2228549Sjkh 2238549Sjkh/* How much space is in this FreeBSD slice? */ 2248549Sjkhstatic int 2258549Sjkhspace_free(struct chunk *c) 2268549Sjkh{ 22712661Speter struct chunk *c1; 2288549Sjkh int sz = c->size; 2298549Sjkh 23012661Speter for (c1 = c->part; c1; c1 = c1->next) { 2318549Sjkh if (c1->type != unused) 2328549Sjkh sz -= c1->size; 2338549Sjkh } 2348549Sjkh if (sz < 0) 2358549Sjkh msgFatal("Partitions are larger than actual chunk??"); 2368549Sjkh return sz; 2378549Sjkh} 2388549Sjkh 2398549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 2408549Sjkhstatic void 24130345Sjkhrecord_label_chunks(Device **devs, Device *dev) 2428549Sjkh{ 2438549Sjkh int i, j, p; 2448549Sjkh struct chunk *c1, *c2; 2458556Sjkh Disk *d; 2468549Sjkh 2478549Sjkh j = p = 0; 2488556Sjkh /* First buzz through and pick up the FreeBSD slices */ 2498549Sjkh for (i = 0; devs[i]; i++) { 25030345Sjkh if ((dev && devs[i] != dev) || !devs[i]->enabled) 2518556Sjkh continue; 2528556Sjkh d = (Disk *)devs[i]->private; 2538556Sjkh if (!d->chunks) 2548556Sjkh msgFatal("No chunk list found for %s!", d->name); 2558549Sjkh 2568556Sjkh /* Put the slice entries first */ 2578556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2588549Sjkh if (c1->type == freebsd) { 2598549Sjkh label_chunk_info[j].type = PART_SLICE; 2608549Sjkh label_chunk_info[j].c = c1; 2618549Sjkh ++j; 2628549Sjkh } 2638549Sjkh } 2648549Sjkh } 26512661Speter 2668556Sjkh /* Now run through again and get the FreeBSD partition entries */ 2678556Sjkh for (i = 0; devs[i]; i++) { 2688556Sjkh if (!devs[i]->enabled) 2698556Sjkh continue; 2708556Sjkh d = (Disk *)devs[i]->private; 2718549Sjkh /* Then buzz through and pick up the partitions */ 2728556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2738549Sjkh if (c1->type == freebsd) { 2748549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 2758549Sjkh if (c2->type == part) { 2768549Sjkh if (c2->subtype == FS_SWAP) 2778549Sjkh label_chunk_info[j].type = PART_SWAP; 2788549Sjkh else 2798549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 2808549Sjkh label_chunk_info[j].c = c2; 2818549Sjkh ++j; 2828549Sjkh } 2838549Sjkh } 2848549Sjkh } 2858549Sjkh else if (c1->type == fat) { 2868549Sjkh label_chunk_info[j].type = PART_FAT; 2878549Sjkh label_chunk_info[j].c = c1; 2888702Sjkh ++j; 2898549Sjkh } 2908549Sjkh } 2918549Sjkh } 2928549Sjkh label_chunk_info[j].c = NULL; 29329249Sjkh if (here >= j) { 2948549Sjkh here = j ? j - 1 : 0; 29529249Sjkh } 2968549Sjkh} 2978549Sjkh 2988549Sjkh/* A new partition entry */ 2998549Sjkhstatic PartInfo * 3008665Sphknew_part(char *mpoint, Boolean newfs, u_long size) 3018549Sjkh{ 3028549Sjkh PartInfo *ret; 3038549Sjkh 3049202Srgrimes if (!mpoint) 3059202Srgrimes mpoint = "/change_me"; 3069202Srgrimes 3078549Sjkh ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 30820247Sjkh sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX); 30949441Sphk strcpy(ret->newfs_cmd, "newfs "); 31049441Sphk strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS)); 3118666Sphk ret->newfs = newfs; 31274086Sjkh ret->soft = 0; 3138669Sphk if (!size) 31429249Sjkh return ret; 3158549Sjkh return ret; 3168549Sjkh} 3178549Sjkh 3188549Sjkh/* Get the mountpoint for a partition and save it away */ 31912661Speterstatic PartInfo * 3208589Sjkhget_mountpoint(struct chunk *old) 3218549Sjkh{ 3228549Sjkh char *val; 3238549Sjkh PartInfo *tmp; 3248549Sjkh 32514793Sjoerg if (old && old->private_data) 32614793Sjoerg tmp = old->private_data; 3278810Sjkh else 3288810Sjkh tmp = NULL; 3298810Sjkh val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 3308764Sjkh if (!val || !*val) { 3318751Sjkh if (!old) 3328751Sjkh return NULL; 3338751Sjkh else { 33414793Sjoerg free(old->private_data); 33514793Sjoerg old->private_data = NULL; 3368751Sjkh } 3378669Sphk return NULL; 3388751Sjkh } 3398669Sphk 3408669Sphk /* Is it just the same value? */ 3418810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 3428669Sphk return NULL; 3438810Sjkh 3448810Sjkh /* Did we use it already? */ 3458669Sphk if (check_conflict(val)) { 3468669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 3478669Sphk return NULL; 3488549Sjkh } 3498810Sjkh 3508810Sjkh /* Is it bogus? */ 3518669Sphk if (*val != '/') { 3528669Sphk msgConfirm("Mount point must start with a / character"); 3538669Sphk return NULL; 3548669Sphk } 3558810Sjkh 3568810Sjkh /* Is it going to be mounted on root? */ 3578669Sphk if (!strcmp(val, "/")) { 3588669Sphk if (old) 3598669Sphk old->flags |= CHUNK_IS_ROOT; 3608810Sjkh } 3618810Sjkh else if (old) 3628669Sphk old->flags &= ~CHUNK_IS_ROOT; 3638810Sjkh 3648810Sjkh safe_free(tmp); 36546615Sjkh val = string_skipwhite(string_prune(val)); 3668669Sphk tmp = new_part(val, TRUE, 0); 3678669Sphk if (old) { 36814793Sjoerg old->private_data = tmp; 3698669Sphk old->private_free = safe_free; 3708669Sphk } 3718669Sphk return tmp; 3728549Sjkh} 3738549Sjkh 3748549Sjkh/* Get the type of the new partiton */ 3758549Sjkhstatic PartType 3768549Sjkhget_partition_type(void) 3778549Sjkh{ 3788549Sjkh char selection[20]; 3798669Sphk int i; 3808549Sjkh static unsigned char *fs_types[] = { 3818549Sjkh "FS", 3828549Sjkh "A file system", 3838549Sjkh "Swap", 3848549Sjkh "A swap partition.", 3858549Sjkh }; 38654587Sjkh WINDOW *w = savescr(); 38754587Sjkh 3888669Sphk i = dialog_menu("Please choose a partition type", 38912661Speter "If you want to use this partition for swap space, select Swap.\n" 39012661Speter "If you want to put a filesystem on it, choose FS.", 39112661Speter -1, -1, 2, 2, fs_types, selection, NULL, NULL); 39254587Sjkh restorescr(w); 3938669Sphk if (!i) { 3948549Sjkh if (!strcmp(selection, "FS")) 3958549Sjkh return PART_FILESYSTEM; 3968549Sjkh else if (!strcmp(selection, "Swap")) 3978549Sjkh return PART_SWAP; 3988549Sjkh } 3998549Sjkh return PART_NONE; 4008549Sjkh} 4018549Sjkh 4028549Sjkh/* If the user wants a special newfs command for this, set it */ 4038549Sjkhstatic void 4048549SjkhgetNewfsCmd(PartInfo *p) 4058549Sjkh{ 4068549Sjkh char *val; 4078549Sjkh 4088549Sjkh val = msgGetInput(p->newfs_cmd, 40912661Speter "Please enter the newfs command and options you'd like to use in\n" 41012661Speter "creating this file system."); 4118549Sjkh if (val) 41220247Sjkh sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 4138549Sjkh} 4148549Sjkh 41576299Sjkh#define MAX_MOUNT_NAME 9 4168549Sjkh 4178549Sjkh#define PART_PART_COL 0 41854014Sjkh#define PART_MOUNT_COL 10 4198549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 42049202Sbrian#define PART_NEWFS_COL (PART_SIZE_COL + 8) 42176299Sjkh#define PART_OFF 38 4228549Sjkh 42329249Sjkh#define TOTAL_AVAIL_LINES (10) 42429249Sjkh#define PSLICE_SHOWABLE (4) 42529249Sjkh 42629249Sjkh 4278549Sjkh/* stick this all up on the screen */ 4288549Sjkhstatic void 4298549Sjkhprint_label_chunks(void) 4308549Sjkh{ 43129249Sjkh int i, j, srow, prow, pcol; 43229249Sjkh int sz; 43329249Sjkh char clrmsg[80]; 43429633Sjkh int ChunkPartStartRow; 43529633Sjkh WINDOW *ChunkWin; 4368549Sjkh 43729249Sjkh /********************************************************/ 43829249Sjkh /*** These values are for controling screen resources ***/ 43929249Sjkh /*** Each label line holds up to 2 labels, so beware! ***/ 44029249Sjkh /*** strategy will be to try to always make sure the ***/ 44129249Sjkh /*** highlighted label is in the active display area. ***/ 44229249Sjkh /********************************************************/ 44329249Sjkh int pslice_max, label_max; 44429249Sjkh int pslice_count, label_count, label_focus_found, pslice_focus_found; 44529249Sjkh 4468549Sjkh attrset(A_REVERSE); 4478549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 4488549Sjkh attrset(A_NORMAL); 4498549Sjkh 45029633Sjkh /*** Count the number of parition slices ***/ 45129633Sjkh pslice_count = 0; 45229633Sjkh for (i = 0; label_chunk_info[i].c ; i++) { 45329633Sjkh if (label_chunk_info[i].type == PART_SLICE) 45429633Sjkh ++pslice_count; 45529633Sjkh } 45629633Sjkh pslice_max = pslice_count; 45729633Sjkh 45829633Sjkh /*** 4 line max for partition slices ***/ 45929633Sjkh if (pslice_max > PSLICE_SHOWABLE) { 46029633Sjkh pslice_max = PSLICE_SHOWABLE; 46129633Sjkh } 46229633Sjkh ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 46329633Sjkh 46429633Sjkh /*** View partition slices modulo pslice_max ***/ 46529633Sjkh label_max = TOTAL_AVAIL_LINES - pslice_max; 46629633Sjkh 4678549Sjkh for (i = 0; i < 2; i++) { 46815440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 46915440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 4708549Sjkh 47115440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 47215440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 4738549Sjkh 47449202Sbrian mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); 47549202Sbrian mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); 4768549Sjkh 47715440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 47815440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 4798549Sjkh } 4808549Sjkh srow = CHUNK_SLICE_START_ROW; 48115440Sjkh prow = 0; 4828549Sjkh pcol = 0; 4838549Sjkh 48429249Sjkh /*** these variables indicate that the focused item is shown currently ***/ 48529249Sjkh label_focus_found = 0; 48629249Sjkh pslice_focus_found = 0; 48729249Sjkh 48829249Sjkh label_count = 0; 48929249Sjkh pslice_count = 0; 49029249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 49129249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 49229249Sjkh 49329633Sjkh ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 49429633Sjkh 49529633Sjkh wclear(ChunkWin); 49629633Sjkh /*** wrefresh(ChunkWin); ***/ 49729633Sjkh 4988751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 4998549Sjkh /* Is it a slice entry displayed at the top? */ 5008549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 50129249Sjkh /*** This causes the new pslice to replace the previous display ***/ 50229249Sjkh /*** focus must remain on the most recently active pslice ***/ 50329249Sjkh if (pslice_count == pslice_max) { 50429249Sjkh if (pslice_focus_found) { 50529249Sjkh /*** This is where we can mark the more following ***/ 50629249Sjkh attrset(A_BOLD); 50729249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 50829249Sjkh attrset(A_NORMAL); 50929249Sjkh continue; 51029249Sjkh } 51129249Sjkh else { 51229249Sjkh /*** this is where we set the more previous ***/ 51329249Sjkh attrset(A_BOLD); 51429249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 51529249Sjkh attrset(A_NORMAL); 51629249Sjkh pslice_count = 0; 51729249Sjkh srow = CHUNK_SLICE_START_ROW; 51829249Sjkh } 51929249Sjkh } 52029249Sjkh 5218549Sjkh sz = space_free(label_chunk_info[i].c); 52215440Sjkh if (i == here) 52316208Sjkh attrset(ATTR_SELECTED); 52429249Sjkh if (i == pslice_focus) 52529249Sjkh pslice_focus_found = -1; 52629249Sjkh 52729249Sjkh mvprintw(srow++, 0, 52829249Sjkh "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 52929249Sjkh label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, 53029249Sjkh sz, (sz / ONE_MEG)); 53115440Sjkh attrset(A_NORMAL); 53215440Sjkh clrtoeol(); 53315440Sjkh move(0, 0); 53429633Sjkh /*** refresh(); ***/ 53529249Sjkh ++pslice_count; 5368549Sjkh } 53715440Sjkh /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 5388549Sjkh else { 53974086Sjkh char onestr[PART_OFF], num[10], *mountpoint, newfs[10]; 5408549Sjkh 5418549Sjkh /* 5428549Sjkh * We copy this into a blank-padded string so that it looks like 5438549Sjkh * a solid bar in reverse-video 5448549Sjkh */ 5458549Sjkh memset(onestr, ' ', PART_OFF - 1); 5468549Sjkh onestr[PART_OFF - 1] = '\0'; 54729249Sjkh 54829249Sjkh /*** Track how many labels have been displayed ***/ 54929249Sjkh if (label_count == ((label_max - 1 ) * 2)) { 55029249Sjkh if (label_focus_found) { 55129249Sjkh continue; 55229249Sjkh } 55329249Sjkh else { 55429249Sjkh label_count = 0; 55529249Sjkh prow = 0; 55629249Sjkh pcol = 0; 55729249Sjkh } 55829249Sjkh } 55929249Sjkh 56015440Sjkh /* Go for two columns if we've written one full columns worth */ 56129249Sjkh /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 56229249Sjkh if (label_count == label_max - 1) { 5638549Sjkh pcol = PART_OFF; 56415440Sjkh prow = 0; 5658549Sjkh } 5668705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 5678549Sjkh /* If it's a filesystem, display the mountpoint */ 56814793Sjoerg if (label_chunk_info[i].c->private_data 56910882Speter && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 57014793Sjoerg mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 57123529Sjkh else if (label_chunk_info[i].type == PART_SWAP) 57223529Sjkh mountpoint = "swap"; 57310882Speter else 57410882Speter mountpoint = "<none>"; 57510882Speter 57610882Speter /* Now display the newfs field */ 57710882Speter if (label_chunk_info[i].type == PART_FAT) 57874086Sjkh strcpy(newfs, "DOS"); 57974086Sjkh else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) { 58074086Sjkh strcpy(newfs, "UFS"); 58176299Sjkh strcat(newfs, 58276299Sjkh ((PartInfo *)label_chunk_info[i].c->private_data)->soft ? 58376299Sjkh "+S" : " "); 58476299Sjkh strcat(newfs, 58576299Sjkh ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? 58676299Sjkh " Y" : " N"); 58774086Sjkh } 58810882Speter else if (label_chunk_info[i].type == PART_SWAP) 58974086Sjkh strcpy(newfs, "SWAP"); 59010882Speter else 59174086Sjkh strcpy(newfs, "*"); 5928549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 5938549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 59449202Sbrian snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 5958549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 5968549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 5978549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 59829633Sjkh if (i == label_focus) { 59929633Sjkh label_focus_found = -1; 60029633Sjkh wattrset(ChunkWin, A_BOLD); 60129633Sjkh } 60215440Sjkh if (i == here) 60316208Sjkh wattrset(ChunkWin, ATTR_SELECTED); 60429249Sjkh 60574086Sjkh /*** lazy man's way of expensively padding this string ***/ 60674086Sjkh while (strlen(onestr) < 37) 60729249Sjkh strcat(onestr, " "); 60829249Sjkh 60915440Sjkh mvwaddstr(ChunkWin, prow, pcol, onestr); 61015440Sjkh wattrset(ChunkWin, A_NORMAL); 61115440Sjkh move(0, 0); 6128549Sjkh ++prow; 61329249Sjkh ++label_count; 6148549Sjkh } 6158549Sjkh } 61629249Sjkh 61729249Sjkh /*** this will erase all the extra stuff ***/ 61829249Sjkh memset(clrmsg, ' ', 37); 61929249Sjkh clrmsg[37] = '\0'; 62029249Sjkh 62129249Sjkh while (pslice_count < pslice_max) { 62229249Sjkh mvprintw(srow++, 0, clrmsg); 62329249Sjkh clrtoeol(); 62429249Sjkh ++pslice_count; 62529249Sjkh } 62629633Sjkh while (label_count < (2 * (label_max - 1))) { 62729633Sjkh mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 62829633Sjkh ++label_count; 62929633Sjkh if (prow == (label_max - 1)) { 63029633Sjkh prow = 0; 63129633Sjkh pcol = PART_OFF; 63229633Sjkh } 63329249Sjkh } 63429633Sjkh refresh(); 63529633Sjkh wrefresh(ChunkWin); 6368549Sjkh} 6378549Sjkh 6388549Sjkhstatic void 63918619Sjkhprint_command_summary(void) 6408549Sjkh{ 6418820Sjkh mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 64274086Sjkh mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 64315440Sjkh if (!RunningAsInit) 64474086Sjkh mvprintw(18, 47, "W = Write"); 64574086Sjkh mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates"); 64674086Sjkh mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults"); 64715695Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 6488549Sjkh move(0, 0); 6498549Sjkh} 6508549Sjkh 65118619Sjkhstatic void 65218619Sjkhclear_wins(void) 65318619Sjkh{ 65429633Sjkh extern void print_label_chunks(); 65518619Sjkh clear(); 65629633Sjkh print_label_chunks(); 65718619Sjkh} 65818619Sjkh 65943392Sjkh#ifdef __alpha__ 66043392Sjkh 66143392Sjkh/* 66243392Sjkh * If there isn't a freebsd chunk already (i.e. there is no label), 66343392Sjkh * dedicate the disk. 66443392Sjkh */ 66543392Sjkhstatic void 66643392Sjkhmaybe_dedicate(Disk* d) 66743392Sjkh{ 66843392Sjkh struct chunk *c; 66943392Sjkh 67043392Sjkh for (c = d->chunks->part; c; c = c->next) { 67143392Sjkh if (c->type == freebsd) 67243392Sjkh break; 67343392Sjkh } 67443392Sjkh 67543392Sjkh if (!c) { 67643392Sjkh msgDebug("dedicating disk"); 67743392Sjkh All_FreeBSD(d, 1); 67843392Sjkh } 67943392Sjkh} 68043392Sjkh 68143392Sjkh#endif 68243392Sjkh 68312661Speterstatic int 68430345SjkhdiskLabel(Device *dev) 6858549Sjkh{ 68618619Sjkh int sz, key = 0; 6878549Sjkh Boolean labeling; 6888549Sjkh char *msg = NULL; 6899202Srgrimes PartInfo *p, *oldp; 6908549Sjkh PartType type; 6918824Sjkh Device **devs; 69242386Sjkh#ifdef __alpha__ 69342386Sjkh int i; 69442386Sjkh#endif 69554587Sjkh WINDOW *w = savescr(); 6968549Sjkh 69729628Sjkh label_focus = 0; 69829628Sjkh pslice_focus = 0; 69929633Sjkh here = 0; 70030345Sjkh 70112661Speter devs = deviceFind(NULL, DEVICE_TYPE_DISK); 70212661Speter if (!devs) { 70312661Speter msgConfirm("No disks found!"); 70454587Sjkh restorescr(w); 70515242Sjkh return DITEM_FAILURE; 70612661Speter } 7078549Sjkh labeling = TRUE; 7088549Sjkh keypad(stdscr, TRUE); 70942386Sjkh#ifdef __alpha__ 71042386Sjkh for (i = 0; devs[i]; i++) { 71143392Sjkh maybe_dedicate((Disk*) devs[i]->private); 71242386Sjkh } 71342386Sjkh#endif 71430345Sjkh record_label_chunks(devs, dev); 7158549Sjkh 71618619Sjkh clear(); 7178549Sjkh while (labeling) { 71818744Sjkh char *cp; 71918744Sjkh 7208549Sjkh print_label_chunks(); 72118619Sjkh print_command_summary(); 7228549Sjkh if (msg) { 72315695Sjkh attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 72412661Speter clrtoeol(); 7258549Sjkh beep(); 7268549Sjkh msg = NULL; 7278549Sjkh } 72815442Sjkh else { 72915442Sjkh move(23, 0); 73015442Sjkh clrtoeol(); 73115442Sjkh } 73218744Sjkh 73318619Sjkh refresh(); 73417397Sjkh key = getch(); 73517397Sjkh switch (toupper(key)) { 73615440Sjkh int i; 73717362Sjkh static char _msg[40]; 7388549Sjkh 7398751Sjkh case '\014': /* ^L */ 74018619Sjkh clear_wins(); 74118619Sjkh break; 7428751Sjkh 74321698Sjkh case '\020': /* ^P */ 7448549Sjkh case KEY_UP: 7458549Sjkh case '-': 7468549Sjkh if (here != 0) 7478549Sjkh --here; 7488751Sjkh else 7498751Sjkh while (label_chunk_info[here + 1].c) 7508751Sjkh ++here; 7518549Sjkh break; 7528549Sjkh 75321698Sjkh case '\016': /* ^N */ 7548549Sjkh case KEY_DOWN: 7558549Sjkh case '+': 7568549Sjkh case '\r': 7578549Sjkh case '\n': 7588751Sjkh if (label_chunk_info[here + 1].c) 7598549Sjkh ++here; 7608751Sjkh else 7618751Sjkh here = 0; 7628549Sjkh break; 7638549Sjkh 7648549Sjkh case KEY_HOME: 7658549Sjkh here = 0; 7668549Sjkh break; 7678549Sjkh 7688549Sjkh case KEY_END: 7698751Sjkh while (label_chunk_info[here + 1].c) 7708549Sjkh ++here; 7718549Sjkh break; 7728549Sjkh 7738549Sjkh case KEY_F(1): 7748549Sjkh case '?': 77512661Speter systemDisplayHelp("partition"); 77618619Sjkh clear_wins(); 7778549Sjkh break; 7788549Sjkh 77910882Speter case 'A': 78010882Speter if (label_chunk_info[here].type != PART_SLICE) { 78115440Sjkh msg = "You can only do this in a disk slice (at top of screen)"; 78210882Speter break; 78310882Speter } 78410882Speter sz = space_free(label_chunk_info[here].c); 78517362Sjkh if (sz <= FS_MIN_SIZE) 78615440Sjkh msg = "Not enough free space to create a new partition in the slice"; 78715440Sjkh else { 78815440Sjkh struct chunk *tmp; 78915440Sjkh int mib[2]; 79015440Sjkh int physmem; 79115440Sjkh size_t size, swsize; 79215440Sjkh char *cp; 79317362Sjkh Chunk *rootdev, *swapdev, *usrdev, *vardev; 79412661Speter 79517368Sjkh (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev); 79617362Sjkh if (!rootdev) { 79717362Sjkh cp = variable_get(VAR_ROOT_SIZE); 79817362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 79944601Sjkh (cp ? atoi(cp) : ROOT_DEFAULT_SIZE) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT); 80017362Sjkh if (!tmp) { 80117362Sjkh msgConfirm("Unable to create the root partition. Too big?"); 80218619Sjkh clear_wins(); 80317362Sjkh break; 80417362Sjkh } 80517362Sjkh tmp->private_data = new_part("/", TRUE, tmp->size); 80617362Sjkh tmp->private_free = safe_free; 80730345Sjkh record_label_chunks(devs, dev); 80815440Sjkh } 80917362Sjkh 81017362Sjkh if (!swapdev) { 81117362Sjkh cp = variable_get(VAR_SWAP_SIZE); 81217362Sjkh if (cp) 81317362Sjkh swsize = atoi(cp) * ONE_MEG; 81417362Sjkh else { 81517362Sjkh mib[0] = CTL_HW; 81617362Sjkh mib[1] = HW_PHYSMEM; 81717362Sjkh size = sizeof physmem; 81817362Sjkh sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 81917362Sjkh swsize = 16 * ONE_MEG + (physmem * 2 / 512); 82017362Sjkh } 82117362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 82217362Sjkh swsize, part, FS_SWAP, 0); 82317362Sjkh if (!tmp) { 82417362Sjkh msgConfirm("Unable to create the swap partition. Too big?"); 82518619Sjkh clear_wins(); 82617362Sjkh break; 82717362Sjkh } 82817362Sjkh tmp->private_data = 0; 82917362Sjkh tmp->private_free = safe_free; 83030345Sjkh record_label_chunks(devs, dev); 83115440Sjkh } 83217362Sjkh 83317362Sjkh if (!vardev) { 83417362Sjkh cp = variable_get(VAR_VAR_SIZE); 83537735Sjkh if (cp) 83637735Sjkh sz = atoi(cp) * ONE_MEG; 83737735Sjkh else 83837735Sjkh sz = variable_get(VAR_NO_USR) 83937735Sjkh ? space_free(label_chunk_info[here].c) 84037735Sjkh : VAR_MIN_SIZE * ONE_MEG; 84137735Sjkh 84217362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 84337735Sjkh sz, part, FS_BSDFFS, 0); 84417362Sjkh if (!tmp) { 84517362Sjkh msgConfirm("Less than %dMB free for /var - you will need to\n" 84617362Sjkh "partition your disk manually with a custom install!", 84717362Sjkh (cp ? atoi(cp) : VAR_MIN_SIZE)); 84818619Sjkh clear_wins(); 84917362Sjkh break; 85017362Sjkh } 85117362Sjkh tmp->private_data = new_part("/var", TRUE, tmp->size); 85217362Sjkh tmp->private_free = safe_free; 85330345Sjkh record_label_chunks(devs, dev); 85415440Sjkh } 85512661Speter 85637735Sjkh if (!usrdev && !variable_get(VAR_NO_USR)) { 85717362Sjkh cp = variable_get(VAR_USR_SIZE); 85817362Sjkh if (cp) 85917362Sjkh sz = atoi(cp) * ONE_MEG; 86017362Sjkh else 86117362Sjkh sz = space_free(label_chunk_info[here].c); 86229501Sjkh if (sz) { 86329501Sjkh if (sz < (USR_MIN_SIZE * ONE_MEG)) { 86429501Sjkh msgConfirm("Less than %dMB free for /usr - you will need to\n" 86529501Sjkh "partition your disk manually with a custom install!", USR_MIN_SIZE); 86629501Sjkh clear_wins(); 86729501Sjkh break; 86829501Sjkh } 86917362Sjkh 87029501Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 87129501Sjkh label_chunk_info[here].c, 87229501Sjkh sz, part, FS_BSDFFS, 0); 87329501Sjkh if (!tmp) { 87429501Sjkh msgConfirm("Unable to create the /usr partition. Not enough space?\n" 87529501Sjkh "You will need to partition your disk manually with a custom install!"); 87629501Sjkh clear_wins(); 87729501Sjkh break; 87829501Sjkh } 87929501Sjkh tmp->private_data = new_part("/usr", TRUE, tmp->size); 88029501Sjkh tmp->private_free = safe_free; 88130345Sjkh record_label_chunks(devs, dev); 88217362Sjkh } 88315440Sjkh } 88437735Sjkh 88515440Sjkh /* At this point, we're reasonably "labelled" */ 88674156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 88743685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 88810882Speter } 88915440Sjkh break; 89010882Speter 8918549Sjkh case 'C': 8928549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 8938549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 8948549Sjkh break; 8958549Sjkh } 8968549Sjkh sz = space_free(label_chunk_info[here].c); 8978669Sphk if (sz <= FS_MIN_SIZE) { 89812661Speter msg = "Not enough space to create an additional FreeBSD partition"; 8998669Sphk break; 9008669Sphk } 90115440Sjkh else { 90218744Sjkh char *val; 9038702Sjkh int size; 9048702Sjkh struct chunk *tmp; 9058820Sjkh char osize[80]; 9068702Sjkh u_long flags = 0; 9078549Sjkh 9088820Sjkh sprintf(osize, "%d", sz); 90918619Sjkh val = msgGetInput(osize, 91057617Sjkh "Please specify the partition size in blocks or append a trailing G for\n" 91157617Sjkh "gigabytes, M for megabytes, or C for cylinders.\n" 91257617Sjkh "%d blocks (%dMB) are free.", 91318619Sjkh sz, sz / ONE_MEG); 91418619Sjkh if (!val || (size = strtol(val, &cp, 0)) <= 0) { 91518619Sjkh clear_wins(); 9168702Sjkh break; 91718619Sjkh } 9188549Sjkh 9198751Sjkh if (*cp) { 9208751Sjkh if (toupper(*cp) == 'M') 9218751Sjkh size *= ONE_MEG; 92257617Sjkh else if (toupper(*cp) == 'G') 92357617Sjkh size *= ONE_GIG; 9248751Sjkh else if (toupper(*cp) == 'C') 9258751Sjkh size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 9268751Sjkh } 9278820Sjkh if (size <= FS_MIN_SIZE) { 9288820Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 92918619Sjkh clear_wins(); 9308820Sjkh break; 9318820Sjkh } 9328702Sjkh type = get_partition_type(); 93318619Sjkh if (type == PART_NONE) { 93418619Sjkh clear_wins(); 93518619Sjkh beep(); 9368669Sphk break; 93718619Sjkh } 9388669Sphk 9398702Sjkh if (type == PART_FILESYSTEM) { 94018619Sjkh if ((p = get_mountpoint(NULL)) == NULL) { 94118619Sjkh clear_wins(); 94218619Sjkh beep(); 9438702Sjkh break; 94418619Sjkh } 9458702Sjkh else if (!strcmp(p->mountpoint, "/")) 9468702Sjkh flags |= CHUNK_IS_ROOT; 9478702Sjkh else 9488702Sjkh flags &= ~CHUNK_IS_ROOT; 94918619Sjkh } 95018619Sjkh else 9518702Sjkh p = NULL; 9528702Sjkh 95376237Sjkh if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) { 95476237Sjkh msgConfirm("Warning: This is smaller than the recommended size for a\n" 95576237Sjkh "root partition. For a variety of reasons, root\n" 95676237Sjkh "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 9578672Sjkh } 9588751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 9598702Sjkh label_chunk_info[here].c, 9608702Sjkh size, part, 9618702Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 9628702Sjkh flags); 9638702Sjkh if (!tmp) { 9648702Sjkh msgConfirm("Unable to create the partition. Too big?"); 96518619Sjkh clear_wins(); 9668672Sjkh break; 9678672Sjkh } 9688702Sjkh if (type != PART_SWAP) { 9698669Sphk /* This is needed to tell the newfs -u about the size */ 97014793Sjoerg tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 9718669Sphk safe_free(p); 97215355Sjkh } 97315355Sjkh else 97414793Sjoerg tmp->private_data = p; 9758702Sjkh tmp->private_free = safe_free; 97674156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 97743685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 97830345Sjkh record_label_chunks(devs, dev); 97918619Sjkh clear_wins(); 98029249Sjkh /*** This is where we assign focus to new label so it shows ***/ 98129249Sjkh { 98229249Sjkh int i; 98329249Sjkh label_focus = -1; 98429249Sjkh for (i = 0; label_chunk_info[i].c; ++i) { 98529249Sjkh if (label_chunk_info[i].c == tmp) { 98629249Sjkh label_focus = i; 98729249Sjkh break; 98829249Sjkh } 98929249Sjkh } 99029249Sjkh if (label_focus == -1) 99129249Sjkh label_focus = i - 1; 99229249Sjkh } 9938549Sjkh } 9948549Sjkh break; 9958549Sjkh 99617397Sjkh case KEY_DC: 9978549Sjkh case 'D': /* delete */ 9988549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 9998549Sjkh msg = MSG_NOT_APPLICABLE; 10008549Sjkh break; 10018549Sjkh } 10028549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 10038705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 10048549Sjkh break; 10058549Sjkh } 10068751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 100774156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 100843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 100930345Sjkh record_label_chunks(devs, dev); 10108549Sjkh break; 10118549Sjkh 10128549Sjkh case 'M': /* mount */ 10138549Sjkh switch(label_chunk_info[here].type) { 10148549Sjkh case PART_SLICE: 10158549Sjkh msg = MSG_NOT_APPLICABLE; 10168549Sjkh break; 10178549Sjkh 10188549Sjkh case PART_SWAP: 10198549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 10208549Sjkh break; 10218549Sjkh 10228556Sjkh case PART_FAT: 10238549Sjkh case PART_FILESYSTEM: 102414793Sjoerg oldp = label_chunk_info[here].c->private_data; 10258589Sjkh p = get_mountpoint(label_chunk_info[here].c); 10268549Sjkh if (p) { 10279202Srgrimes if (!oldp) 10289202Srgrimes p->newfs = FALSE; 10298722Sjkh if (label_chunk_info[here].type == PART_FAT 10308722Sjkh && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 10318722Sjkh || !strcmp(p->mountpoint, "/var"))) { 10328722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 10338722Sjkh strcpy(p->mountpoint, "/bogus"); 10348722Sjkh } 10358549Sjkh } 103674156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 103743685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 103830345Sjkh record_label_chunks(devs, dev); 103918636Sjkh clear_wins(); 10408549Sjkh break; 10418549Sjkh 10428549Sjkh default: 10438549Sjkh msgFatal("Bogus partition under cursor???"); 10448549Sjkh break; 10458549Sjkh } 10468549Sjkh break; 10478549Sjkh 10488549Sjkh case 'N': /* Set newfs options */ 104914793Sjoerg if (label_chunk_info[here].c->private_data && 105014793Sjoerg ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 105114793Sjoerg getNewfsCmd(label_chunk_info[here].c->private_data); 10528549Sjkh else 10538549Sjkh msg = MSG_NOT_APPLICABLE; 105418636Sjkh clear_wins(); 10558549Sjkh break; 10568549Sjkh 105774086Sjkh case 'S': /* Toggle soft updates flag */ 105874086Sjkh if (label_chunk_info[here].type == PART_FILESYSTEM) { 105974086Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 106074086Sjkh if (pi) 106174086Sjkh pi->soft = !pi->soft; 106274086Sjkh else 106374086Sjkh msg = MSG_NOT_APPLICABLE; 106474086Sjkh } 106574156Sjkh else 106674156Sjkh msg = MSG_NOT_APPLICABLE; 106774086Sjkh break; 106874086Sjkh 10698549Sjkh case 'T': /* Toggle newfs state */ 10709202Srgrimes if (label_chunk_info[here].type == PART_FILESYSTEM) { 107123729Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 107223729Sjkh label_chunk_info[here].c->private_data = 107323729Sjkh new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 107474156Sjkh if (pi && pi->soft) 107574156Sjkh ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1; 107623729Sjkh safe_free(pi); 107723729Sjkh label_chunk_info[here].c->private_free = safe_free; 107874156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 107943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 108018619Sjkh } 10818549Sjkh else 10828549Sjkh msg = MSG_NOT_APPLICABLE; 10838549Sjkh break; 10848549Sjkh 10858820Sjkh case 'U': 108612661Speter clear(); 108774156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 108818744Sjkh msgConfirm("You've already written out your changes -\n" 108918744Sjkh "it's too late to undo!"); 109018744Sjkh } 109170005Sjkh else if (!msgNoYes("Are you SURE you want to Undo everything?")) { 109218744Sjkh variable_unset(DISK_PARTITIONED); 109318744Sjkh variable_unset(DISK_LABELLED); 109418744Sjkh for (i = 0; devs[i]; i++) { 109518744Sjkh Disk *d; 109612661Speter 109718744Sjkh if (!devs[i]->enabled) 109818744Sjkh continue; 109918744Sjkh else if ((d = Open_Disk(devs[i]->name)) != NULL) { 110018744Sjkh Free_Disk(devs[i]->private); 110118744Sjkh devs[i]->private = d; 110230345Sjkh diskPartition(devs[i]); 110318744Sjkh } 11048824Sjkh } 110530345Sjkh record_label_chunks(devs, dev); 11068824Sjkh } 110718636Sjkh clear_wins(); 11088824Sjkh break; 11098820Sjkh 11108549Sjkh case 'W': 111174156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 111218744Sjkh msgConfirm("You've already written out your changes - if you\n" 111374156Sjkh "wish to overwrite them, you'll have to restart\n" 111474156Sjkh "sysinstall first."); 111518744Sjkh } 111670005Sjkh else if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" 111718687Sjkh "installation. If you are installing FreeBSD for the first time\n" 111818687Sjkh "then you should simply type Q when you're finished here and your\n" 111918687Sjkh "changes will be committed in one batch automatically at the end of\n" 112018687Sjkh "these questions.\n\n" 112118687Sjkh "Are you absolutely sure you want to do this now?")) { 112243685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 112312661Speter diskLabelCommit(NULL); 112412661Speter } 112518636Sjkh clear_wins(); 112610882Speter break; 112710882Speter 112810882Speter case '|': 112970005Sjkh if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n" 113012661Speter "This is an entirely undocumented feature which you are not\n" 113112661Speter "expected to understand!")) { 11328549Sjkh int i; 11338549Sjkh Device **devs; 11348549Sjkh 11358549Sjkh dialog_clear(); 11368549Sjkh end_dialog(); 11378549Sjkh DialogActive = FALSE; 11388549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 11398549Sjkh if (!devs) { 114012661Speter msgConfirm("Can't find any disk devices!"); 11418549Sjkh break; 11428549Sjkh } 11438668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 11448613Sjkh if (devs[i]->enabled) 11458613Sjkh slice_wizard(((Disk *)devs[i]->private)); 11468613Sjkh } 114774156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 114843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 11498665Sphk DialogActive = TRUE; 115030345Sjkh record_label_chunks(devs, dev); 115118636Sjkh clear_wins(); 11528549Sjkh } 11538549Sjkh else 11548549Sjkh msg = "A most prudent choice!"; 11558549Sjkh break; 11568549Sjkh 115721698Sjkh case '\033': /* ESC */ 11589202Srgrimes case 'Q': 11598549Sjkh labeling = FALSE; 11608549Sjkh break; 11618549Sjkh 11628549Sjkh default: 11638549Sjkh beep(); 116417362Sjkh sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 116517362Sjkh msg = _msg; 11668549Sjkh break; 11678549Sjkh } 116829633Sjkh if (label_chunk_info[here].type == PART_SLICE) 116929633Sjkh pslice_focus = here; 117029633Sjkh else 117129633Sjkh label_focus = here; 11728549Sjkh } 117354587Sjkh restorescr(w); 117454587Sjkh return DITEM_SUCCESS; 11758549Sjkh} 117626456Sjkh 117726456Sjkhstatic int 117830345SjkhdiskLabelNonInteractive(Device *dev) 117926456Sjkh{ 118026456Sjkh char *cp; 118126456Sjkh PartType type; 118226456Sjkh PartInfo *p; 118326456Sjkh u_long flags = 0; 118426456Sjkh int i, status; 118526456Sjkh Device **devs; 118626456Sjkh Disk *d; 118754587Sjkh 118826456Sjkh status = DITEM_SUCCESS; 118926456Sjkh cp = variable_get(VAR_DISK); 119026456Sjkh if (!cp) { 119126456Sjkh msgConfirm("diskLabel: No disk selected - can't label automatically."); 119226456Sjkh return DITEM_FAILURE; 119326456Sjkh } 119426456Sjkh devs = deviceFind(cp, DEVICE_TYPE_DISK); 119526456Sjkh if (!devs) { 119626456Sjkh msgConfirm("diskLabel: No disk device %s found!", cp); 119726456Sjkh return DITEM_FAILURE; 119826456Sjkh } 119930345Sjkh if (dev) 120030345Sjkh d = dev->private; 120130345Sjkh else 120230345Sjkh d = devs[0]->private; 120342386Sjkh#ifdef __alpha__ 120443392Sjkh maybe_dedicate(d); 120542386Sjkh#endif 120630345Sjkh record_label_chunks(devs, dev); 120726456Sjkh for (i = 0; label_chunk_info[i].c; i++) { 120826456Sjkh Chunk *c1 = label_chunk_info[i].c; 120926456Sjkh 121026456Sjkh if (label_chunk_info[i].type == PART_SLICE) { 121128075Sjkh char name[512]; 121274674Sjkh int entries = 1; 121326456Sjkh 121428075Sjkh while (entries) { 121528075Sjkh snprintf(name, sizeof name, "%s-%d", c1->name, entries); 121628075Sjkh if ((cp = variable_get(name)) != NULL) { 121774674Sjkh int sz, soft = 0; 121828075Sjkh char typ[10], mpoint[50]; 121926456Sjkh 122074156Sjkh if (sscanf(cp, "%s %d %s %d", typ, &sz, mpoint, &soft) < 3) { 122128075Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 122226456Sjkh status = DITEM_FAILURE; 122326456Sjkh continue; 122426456Sjkh } 122526456Sjkh else { 122628075Sjkh Chunk *tmp; 122728075Sjkh 122828075Sjkh if (!strcmp(typ, "swap")) { 122928075Sjkh type = PART_SWAP; 123028075Sjkh strcpy(mpoint, "SWAP"); 123128075Sjkh } 123228075Sjkh else { 123328075Sjkh type = PART_FILESYSTEM; 123428075Sjkh if (!strcmp(mpoint, "/")) 123528075Sjkh flags |= CHUNK_IS_ROOT; 123633132Sjkh else 123733132Sjkh flags &= ~CHUNK_IS_ROOT; 123828075Sjkh } 123928075Sjkh if (!sz) 124028075Sjkh sz = space_free(c1); 124128075Sjkh if (sz > space_free(c1)) { 124228075Sjkh msgConfirm("Not enough free space to create partition: %s", mpoint); 124328075Sjkh status = DITEM_FAILURE; 124428075Sjkh continue; 124528075Sjkh } 124628075Sjkh if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 124728075Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 124828075Sjkh msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 124928075Sjkh status = DITEM_FAILURE; 125028075Sjkh break; 125128075Sjkh } 125228075Sjkh else { 125328075Sjkh tmp->private_data = new_part(mpoint, TRUE, sz); 125428075Sjkh tmp->private_free = safe_free; 125574674Sjkh ((PartInfo *)tmp->private_data)->soft = soft; 125628075Sjkh status = DITEM_SUCCESS; 125728075Sjkh } 125826456Sjkh } 125928075Sjkh entries++; 126026456Sjkh } 126128075Sjkh else { 126228075Sjkh /* No more matches, leave the loop */ 126328075Sjkh entries = 0; 126428075Sjkh } 126526456Sjkh } 126626456Sjkh } 126726456Sjkh else { 126828075Sjkh /* Must be something we can set a mountpoint for */ 126926456Sjkh cp = variable_get(c1->name); 127026456Sjkh if (cp) { 127128075Sjkh char mpoint[50], do_newfs[8]; 127226456Sjkh Boolean newfs = FALSE; 127326456Sjkh 127428075Sjkh do_newfs[0] = '\0'; 127528075Sjkh if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 127626456Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 127726456Sjkh status = DITEM_FAILURE; 127826456Sjkh continue; 127926456Sjkh } 128028075Sjkh newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 128126456Sjkh if (c1->private_data) { 128226456Sjkh p = c1->private_data; 128326456Sjkh p->newfs = newfs; 128426456Sjkh strcpy(p->mountpoint, mpoint); 128526456Sjkh } 128626456Sjkh else { 128726456Sjkh c1->private_data = new_part(mpoint, newfs, 0); 128826456Sjkh c1->private_free = safe_free; 128926456Sjkh } 129026456Sjkh if (!strcmp(mpoint, "/")) 129126456Sjkh c1->flags |= CHUNK_IS_ROOT; 129226456Sjkh else 129326456Sjkh c1->flags &= ~CHUNK_IS_ROOT; 129426456Sjkh } 129526456Sjkh } 129626456Sjkh } 129726456Sjkh if (status == DITEM_SUCCESS) 129843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 129926456Sjkh return status; 130026456Sjkh} 1301