label.c revision 54587
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 54587 1999-12-14 04:25:29Z 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__ 6645127Sjkh#define ROOT_DEFAULT_SIZE 60 6744601Sjkh#else 6845127Sjkh#define ROOT_DEFAULT_SIZE 40 6944601Sjkh#endif 7044601Sjkh 7112661Speter/* The smallest swap partition we want to create by default */ 7212661Speter#define SWAP_MIN_SIZE 16 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) { 17718744Sjkh char *cp; 17818744Sjkh 17918744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 18043685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 18118744Sjkh } 18212661Speter return i; 18312661Speter} 18412661Speter 18512661Speterint 18615091SjkhdiskLabelCommit(dialogMenuItem *self) 18712661Speter{ 18812661Speter char *cp; 18912661Speter int i; 19012661Speter 19112661Speter /* Already done? */ 19217025Sjkh if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 19315242Sjkh i = DITEM_SUCCESS; 19412661Speter else if (!cp) { 19512661Speter msgConfirm("You must assign disk labels before this option can be used."); 19615242Sjkh i = DITEM_FAILURE; 19712661Speter } 19812661Speter /* The routine will guard against redundant writes, just as this one does */ 19915419Sjkh else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 20015242Sjkh i = DITEM_FAILURE; 20115419Sjkh else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 20215242Sjkh i = DITEM_FAILURE; 20312661Speter else { 20412661Speter msgInfo("All filesystem information written successfully."); 20543685Sjkh variable_set2(DISK_LABELLED, "written", 0); 20615242Sjkh i = DITEM_SUCCESS; 20712661Speter } 20812661Speter return i; 20912661Speter} 21012661Speter 2118549Sjkh/* See if we're already using a desired partition name */ 2128549Sjkhstatic Boolean 2138549Sjkhcheck_conflict(char *name) 2148549Sjkh{ 2158549Sjkh int i; 2168549Sjkh 2178751Sjkh for (i = 0; label_chunk_info[i].c; i++) 21823729Sjkh if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) 21923729Sjkh && label_chunk_info[i].c->private_data 22014793Sjoerg && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 2218549Sjkh return TRUE; 2228549Sjkh return FALSE; 2238549Sjkh} 2248549Sjkh 2258549Sjkh/* How much space is in this FreeBSD slice? */ 2268549Sjkhstatic int 2278549Sjkhspace_free(struct chunk *c) 2288549Sjkh{ 22912661Speter struct chunk *c1; 2308549Sjkh int sz = c->size; 2318549Sjkh 23212661Speter for (c1 = c->part; c1; c1 = c1->next) { 2338549Sjkh if (c1->type != unused) 2348549Sjkh sz -= c1->size; 2358549Sjkh } 2368549Sjkh if (sz < 0) 2378549Sjkh msgFatal("Partitions are larger than actual chunk??"); 2388549Sjkh return sz; 2398549Sjkh} 2408549Sjkh 2418549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 2428549Sjkhstatic void 24330345Sjkhrecord_label_chunks(Device **devs, Device *dev) 2448549Sjkh{ 2458549Sjkh int i, j, p; 2468549Sjkh struct chunk *c1, *c2; 2478556Sjkh Disk *d; 2488549Sjkh 2498549Sjkh j = p = 0; 2508556Sjkh /* First buzz through and pick up the FreeBSD slices */ 2518549Sjkh for (i = 0; devs[i]; i++) { 25230345Sjkh if ((dev && devs[i] != dev) || !devs[i]->enabled) 2538556Sjkh continue; 2548556Sjkh d = (Disk *)devs[i]->private; 2558556Sjkh if (!d->chunks) 2568556Sjkh msgFatal("No chunk list found for %s!", d->name); 2578549Sjkh 2588556Sjkh /* Put the slice entries first */ 2598556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2608549Sjkh if (c1->type == freebsd) { 2618549Sjkh label_chunk_info[j].type = PART_SLICE; 2628549Sjkh label_chunk_info[j].c = c1; 2638549Sjkh ++j; 2648549Sjkh } 2658549Sjkh } 2668549Sjkh } 26712661Speter 2688556Sjkh /* Now run through again and get the FreeBSD partition entries */ 2698556Sjkh for (i = 0; devs[i]; i++) { 2708556Sjkh if (!devs[i]->enabled) 2718556Sjkh continue; 2728556Sjkh d = (Disk *)devs[i]->private; 2738549Sjkh /* Then buzz through and pick up the partitions */ 2748556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2758549Sjkh if (c1->type == freebsd) { 2768549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 2778549Sjkh if (c2->type == part) { 2788549Sjkh if (c2->subtype == FS_SWAP) 2798549Sjkh label_chunk_info[j].type = PART_SWAP; 2808549Sjkh else 2818549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 2828549Sjkh label_chunk_info[j].c = c2; 2838549Sjkh ++j; 2848549Sjkh } 2858549Sjkh } 2868549Sjkh } 2878549Sjkh else if (c1->type == fat) { 2888549Sjkh label_chunk_info[j].type = PART_FAT; 2898549Sjkh label_chunk_info[j].c = c1; 2908702Sjkh ++j; 2918549Sjkh } 2928549Sjkh } 2938549Sjkh } 2948549Sjkh label_chunk_info[j].c = NULL; 29529249Sjkh if (here >= j) { 2968549Sjkh here = j ? j - 1 : 0; 29729249Sjkh } 2988549Sjkh} 2998549Sjkh 3008549Sjkh/* A new partition entry */ 3018549Sjkhstatic PartInfo * 3028665Sphknew_part(char *mpoint, Boolean newfs, u_long size) 3038549Sjkh{ 3048549Sjkh PartInfo *ret; 3058549Sjkh 3069202Srgrimes if (!mpoint) 3079202Srgrimes mpoint = "/change_me"; 3089202Srgrimes 3098549Sjkh ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 31020247Sjkh sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX); 31149441Sphk strcpy(ret->newfs_cmd, "newfs "); 31249441Sphk strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS)); 3138666Sphk ret->newfs = newfs; 3148669Sphk if (!size) 31529249Sjkh return ret; 3168549Sjkh return ret; 3178549Sjkh} 3188549Sjkh 3198549Sjkh/* Get the mountpoint for a partition and save it away */ 32012661Speterstatic PartInfo * 3218589Sjkhget_mountpoint(struct chunk *old) 3228549Sjkh{ 3238549Sjkh char *val; 3248549Sjkh PartInfo *tmp; 3258549Sjkh 32614793Sjoerg if (old && old->private_data) 32714793Sjoerg tmp = old->private_data; 3288810Sjkh else 3298810Sjkh tmp = NULL; 33018619Sjkh if (!old) { 33118621Sjkh DialogX = 14; 33218621Sjkh DialogY = 16; 33318619Sjkh } 3348810Sjkh val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 33518619Sjkh DialogX = DialogY = 0; 3368764Sjkh if (!val || !*val) { 3378751Sjkh if (!old) 3388751Sjkh return NULL; 3398751Sjkh else { 34014793Sjoerg free(old->private_data); 34114793Sjoerg old->private_data = NULL; 3428751Sjkh } 3438669Sphk return NULL; 3448751Sjkh } 3458669Sphk 3468669Sphk /* Is it just the same value? */ 3478810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 3488669Sphk return NULL; 3498810Sjkh 3508810Sjkh /* Did we use it already? */ 3518669Sphk if (check_conflict(val)) { 3528669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 3538669Sphk return NULL; 3548549Sjkh } 3558810Sjkh 3568810Sjkh /* Is it bogus? */ 3578669Sphk if (*val != '/') { 3588669Sphk msgConfirm("Mount point must start with a / character"); 3598669Sphk return NULL; 3608669Sphk } 3618810Sjkh 3628810Sjkh /* Is it going to be mounted on root? */ 3638669Sphk if (!strcmp(val, "/")) { 3648669Sphk if (old) 3658669Sphk old->flags |= CHUNK_IS_ROOT; 3668810Sjkh } 3678810Sjkh else if (old) 3688669Sphk old->flags &= ~CHUNK_IS_ROOT; 3698810Sjkh 3708810Sjkh safe_free(tmp); 37146615Sjkh val = string_skipwhite(string_prune(val)); 3728669Sphk tmp = new_part(val, TRUE, 0); 3738669Sphk if (old) { 37414793Sjoerg old->private_data = tmp; 3758669Sphk old->private_free = safe_free; 3768669Sphk } 3778669Sphk return tmp; 3788549Sjkh} 3798549Sjkh 3808549Sjkh/* Get the type of the new partiton */ 3818549Sjkhstatic PartType 3828549Sjkhget_partition_type(void) 3838549Sjkh{ 3848549Sjkh char selection[20]; 3858669Sphk int i; 3868549Sjkh static unsigned char *fs_types[] = { 3878549Sjkh "FS", 3888549Sjkh "A file system", 3898549Sjkh "Swap", 3908549Sjkh "A swap partition.", 3918549Sjkh }; 39254587Sjkh WINDOW *w = savescr(); 39354587Sjkh 39418619Sjkh DialogX = 7; 39518621Sjkh DialogY = 8; 3968669Sphk i = dialog_menu("Please choose a partition type", 39712661Speter "If you want to use this partition for swap space, select Swap.\n" 39812661Speter "If you want to put a filesystem on it, choose FS.", 39912661Speter -1, -1, 2, 2, fs_types, selection, NULL, NULL); 40018619Sjkh DialogX = DialogY = 0; 40154587Sjkh restorescr(w); 4028669Sphk if (!i) { 4038549Sjkh if (!strcmp(selection, "FS")) 4048549Sjkh return PART_FILESYSTEM; 4058549Sjkh else if (!strcmp(selection, "Swap")) 4068549Sjkh return PART_SWAP; 4078549Sjkh } 4088549Sjkh return PART_NONE; 4098549Sjkh} 4108549Sjkh 4118549Sjkh/* If the user wants a special newfs command for this, set it */ 4128549Sjkhstatic void 4138549SjkhgetNewfsCmd(PartInfo *p) 4148549Sjkh{ 4158549Sjkh char *val; 4168549Sjkh 4178549Sjkh val = msgGetInput(p->newfs_cmd, 41812661Speter "Please enter the newfs command and options you'd like to use in\n" 41912661Speter "creating this file system."); 4208549Sjkh if (val) 42120247Sjkh sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 4228549Sjkh} 4238549Sjkh 42454014Sjkh#define MAX_MOUNT_NAME 10 4258549Sjkh 4268549Sjkh#define PART_PART_COL 0 42754014Sjkh#define PART_MOUNT_COL 10 4288549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 42949202Sbrian#define PART_NEWFS_COL (PART_SIZE_COL + 8) 43054473Sjkh#define PART_OFF 38 4318549Sjkh 43229249Sjkh#define TOTAL_AVAIL_LINES (10) 43329249Sjkh#define PSLICE_SHOWABLE (4) 43429249Sjkh 43529249Sjkh 4368549Sjkh/* stick this all up on the screen */ 4378549Sjkhstatic void 4388549Sjkhprint_label_chunks(void) 4398549Sjkh{ 44029249Sjkh int i, j, srow, prow, pcol; 44129249Sjkh int sz; 44229249Sjkh char clrmsg[80]; 44329633Sjkh int ChunkPartStartRow; 44429633Sjkh WINDOW *ChunkWin; 4458549Sjkh 44629249Sjkh /********************************************************/ 44729249Sjkh /*** These values are for controling screen resources ***/ 44829249Sjkh /*** Each label line holds up to 2 labels, so beware! ***/ 44929249Sjkh /*** strategy will be to try to always make sure the ***/ 45029249Sjkh /*** highlighted label is in the active display area. ***/ 45129249Sjkh /********************************************************/ 45229249Sjkh int pslice_max, label_max; 45329249Sjkh int pslice_count, label_count, label_focus_found, pslice_focus_found; 45429249Sjkh 4558549Sjkh attrset(A_REVERSE); 4568549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 4578549Sjkh attrset(A_NORMAL); 4588549Sjkh 45929633Sjkh /*** Count the number of parition slices ***/ 46029633Sjkh pslice_count = 0; 46129633Sjkh for (i = 0; label_chunk_info[i].c ; i++) { 46229633Sjkh if (label_chunk_info[i].type == PART_SLICE) 46329633Sjkh ++pslice_count; 46429633Sjkh } 46529633Sjkh pslice_max = pslice_count; 46629633Sjkh 46729633Sjkh /*** 4 line max for partition slices ***/ 46829633Sjkh if (pslice_max > PSLICE_SHOWABLE) { 46929633Sjkh pslice_max = PSLICE_SHOWABLE; 47029633Sjkh } 47129633Sjkh ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 47229633Sjkh 47329633Sjkh /*** View partition slices modulo pslice_max ***/ 47429633Sjkh label_max = TOTAL_AVAIL_LINES - pslice_max; 47529633Sjkh 4768549Sjkh for (i = 0; i < 2; i++) { 47715440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 47815440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 4798549Sjkh 48015440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 48115440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 4828549Sjkh 48349202Sbrian mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); 48449202Sbrian mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); 4858549Sjkh 48615440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 48715440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 4888549Sjkh } 4898549Sjkh srow = CHUNK_SLICE_START_ROW; 49015440Sjkh prow = 0; 4918549Sjkh pcol = 0; 4928549Sjkh 49329249Sjkh /*** these variables indicate that the focused item is shown currently ***/ 49429249Sjkh label_focus_found = 0; 49529249Sjkh pslice_focus_found = 0; 49629249Sjkh 49729249Sjkh label_count = 0; 49829249Sjkh pslice_count = 0; 49929249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 50029249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 50129249Sjkh 50229633Sjkh ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 50329633Sjkh 50429633Sjkh wclear(ChunkWin); 50529633Sjkh /*** wrefresh(ChunkWin); ***/ 50629633Sjkh 5078751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 5088549Sjkh /* Is it a slice entry displayed at the top? */ 5098549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 51029249Sjkh /*** This causes the new pslice to replace the previous display ***/ 51129249Sjkh /*** focus must remain on the most recently active pslice ***/ 51229249Sjkh if (pslice_count == pslice_max) { 51329249Sjkh if (pslice_focus_found) { 51429249Sjkh /*** This is where we can mark the more following ***/ 51529249Sjkh attrset(A_BOLD); 51629249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 51729249Sjkh attrset(A_NORMAL); 51829249Sjkh continue; 51929249Sjkh } 52029249Sjkh else { 52129249Sjkh /*** this is where we set the more previous ***/ 52229249Sjkh attrset(A_BOLD); 52329249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 52429249Sjkh attrset(A_NORMAL); 52529249Sjkh pslice_count = 0; 52629249Sjkh srow = CHUNK_SLICE_START_ROW; 52729249Sjkh } 52829249Sjkh } 52929249Sjkh 5308549Sjkh sz = space_free(label_chunk_info[i].c); 53115440Sjkh if (i == here) 53216208Sjkh attrset(ATTR_SELECTED); 53329249Sjkh if (i == pslice_focus) 53429249Sjkh pslice_focus_found = -1; 53529249Sjkh 53629249Sjkh mvprintw(srow++, 0, 53729249Sjkh "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 53829249Sjkh label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, 53929249Sjkh sz, (sz / ONE_MEG)); 54015440Sjkh attrset(A_NORMAL); 54115440Sjkh clrtoeol(); 54215440Sjkh move(0, 0); 54329633Sjkh /*** refresh(); ***/ 54429249Sjkh ++pslice_count; 5458549Sjkh } 54615440Sjkh /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 5478549Sjkh else { 5488549Sjkh char onestr[PART_OFF], num[10], *mountpoint, *newfs; 5498549Sjkh 5508549Sjkh /* 5518549Sjkh * We copy this into a blank-padded string so that it looks like 5528549Sjkh * a solid bar in reverse-video 5538549Sjkh */ 5548549Sjkh memset(onestr, ' ', PART_OFF - 1); 5558549Sjkh onestr[PART_OFF - 1] = '\0'; 55629249Sjkh 55729249Sjkh /*** Track how many labels have been displayed ***/ 55829249Sjkh if (label_count == ((label_max - 1 ) * 2)) { 55929249Sjkh if (label_focus_found) { 56029249Sjkh continue; 56129249Sjkh } 56229249Sjkh else { 56329249Sjkh label_count = 0; 56429249Sjkh prow = 0; 56529249Sjkh pcol = 0; 56629249Sjkh } 56729249Sjkh } 56829249Sjkh 56915440Sjkh /* Go for two columns if we've written one full columns worth */ 57029249Sjkh /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 57129249Sjkh if (label_count == label_max - 1) { 5728549Sjkh pcol = PART_OFF; 57315440Sjkh prow = 0; 5748549Sjkh } 5758705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 5768549Sjkh /* If it's a filesystem, display the mountpoint */ 57714793Sjoerg if (label_chunk_info[i].c->private_data 57810882Speter && (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)) 57914793Sjoerg mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 58023529Sjkh else if (label_chunk_info[i].type == PART_SWAP) 58123529Sjkh mountpoint = "swap"; 58210882Speter else 58310882Speter mountpoint = "<none>"; 58410882Speter 58510882Speter /* Now display the newfs field */ 58610882Speter if (label_chunk_info[i].type == PART_FAT) 58710882Speter newfs = "DOS"; 58814793Sjoerg else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) 58914793Sjoerg newfs = ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ? "UFS Y" : "UFS N"; 59010882Speter else if (label_chunk_info[i].type == PART_SWAP) 59110882Speter newfs = "SWAP"; 59210882Speter else 5938549Sjkh newfs = "*"; 5948549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 5958549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 59649202Sbrian snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 5978549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 5988549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 5998549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 60029633Sjkh if (i == label_focus) { 60129633Sjkh label_focus_found = -1; 60229633Sjkh wattrset(ChunkWin, A_BOLD); 60329633Sjkh } 60415440Sjkh if (i == here) 60516208Sjkh wattrset(ChunkWin, ATTR_SELECTED); 60629249Sjkh 60729249Sjkh /*** lazy man's way of padding this string ***/ 60829249Sjkh while (strlen( onestr ) < 37) 60929249Sjkh strcat(onestr, " "); 61029249Sjkh 61115440Sjkh mvwaddstr(ChunkWin, prow, pcol, onestr); 61215440Sjkh wattrset(ChunkWin, A_NORMAL); 61315440Sjkh move(0, 0); 6148549Sjkh ++prow; 61529249Sjkh ++label_count; 6168549Sjkh } 6178549Sjkh } 61829249Sjkh 61929249Sjkh /*** this will erase all the extra stuff ***/ 62029249Sjkh memset(clrmsg, ' ', 37); 62129249Sjkh clrmsg[37] = '\0'; 62229249Sjkh 62329249Sjkh while (pslice_count < pslice_max) { 62429249Sjkh mvprintw(srow++, 0, clrmsg); 62529249Sjkh clrtoeol(); 62629249Sjkh ++pslice_count; 62729249Sjkh } 62829633Sjkh while (label_count < (2 * (label_max - 1))) { 62929633Sjkh mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 63029633Sjkh ++label_count; 63129633Sjkh if (prow == (label_max - 1)) { 63229633Sjkh prow = 0; 63329633Sjkh pcol = PART_OFF; 63429633Sjkh } 63529249Sjkh } 63629633Sjkh refresh(); 63729633Sjkh wrefresh(ChunkWin); 6388549Sjkh} 6398549Sjkh 6408549Sjkhstatic void 64118619Sjkhprint_command_summary(void) 6428549Sjkh{ 6438820Sjkh mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 64421971Sjkh mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 64515440Sjkh if (!RunningAsInit) 64630956Sobrien mvprintw(18, 49, "W = Write"); 64730956Sobrien mvprintw(19, 0, "N = Newfs Opts T = Newfs Toggle U = Undo Q = Finish"); 64810882Speter mvprintw(20, 0, "A = Auto Defaults for all!"); 64915695Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 6508549Sjkh move(0, 0); 6518549Sjkh} 6528549Sjkh 65318619Sjkhstatic void 65418619Sjkhclear_wins(void) 65518619Sjkh{ 65629633Sjkh extern void print_label_chunks(); 65718619Sjkh clear(); 65829633Sjkh print_label_chunks(); 65918619Sjkh} 66018619Sjkh 66143392Sjkh#ifdef __alpha__ 66243392Sjkh 66343392Sjkh/* 66443392Sjkh * If there isn't a freebsd chunk already (i.e. there is no label), 66543392Sjkh * dedicate the disk. 66643392Sjkh */ 66743392Sjkhstatic void 66843392Sjkhmaybe_dedicate(Disk* d) 66943392Sjkh{ 67043392Sjkh struct chunk *c; 67143392Sjkh 67243392Sjkh for (c = d->chunks->part; c; c = c->next) { 67343392Sjkh if (c->type == freebsd) 67443392Sjkh break; 67543392Sjkh } 67643392Sjkh 67743392Sjkh if (!c) { 67843392Sjkh msgDebug("dedicating disk"); 67943392Sjkh All_FreeBSD(d, 1); 68043392Sjkh } 68143392Sjkh} 68243392Sjkh 68343392Sjkh#endif 68443392Sjkh 68512661Speterstatic int 68630345SjkhdiskLabel(Device *dev) 6878549Sjkh{ 68818619Sjkh int sz, key = 0; 6898549Sjkh Boolean labeling; 6908549Sjkh char *msg = NULL; 6919202Srgrimes PartInfo *p, *oldp; 6928549Sjkh PartType type; 6938824Sjkh Device **devs; 69442386Sjkh#ifdef __alpha__ 69542386Sjkh int i; 69642386Sjkh#endif 69754587Sjkh WINDOW *w = savescr(); 6988549Sjkh 69929628Sjkh label_focus = 0; 70029628Sjkh pslice_focus = 0; 70129633Sjkh here = 0; 70230345Sjkh 70312661Speter devs = deviceFind(NULL, DEVICE_TYPE_DISK); 70412661Speter if (!devs) { 70512661Speter msgConfirm("No disks found!"); 70654587Sjkh restorescr(w); 70715242Sjkh return DITEM_FAILURE; 70812661Speter } 7098549Sjkh labeling = TRUE; 7108549Sjkh keypad(stdscr, TRUE); 71142386Sjkh#ifdef __alpha__ 71242386Sjkh for (i = 0; devs[i]; i++) { 71343392Sjkh maybe_dedicate((Disk*) devs[i]->private); 71442386Sjkh } 71542386Sjkh#endif 71630345Sjkh record_label_chunks(devs, dev); 7178549Sjkh 71818619Sjkh clear(); 7198549Sjkh while (labeling) { 72018744Sjkh char *cp; 72118744Sjkh 7228549Sjkh print_label_chunks(); 72318619Sjkh print_command_summary(); 7248549Sjkh if (msg) { 72515695Sjkh attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 72612661Speter clrtoeol(); 7278549Sjkh beep(); 7288549Sjkh msg = NULL; 7298549Sjkh } 73015442Sjkh else { 73115442Sjkh move(23, 0); 73215442Sjkh clrtoeol(); 73315442Sjkh } 73418744Sjkh 73518619Sjkh refresh(); 73617397Sjkh key = getch(); 73717397Sjkh switch (toupper(key)) { 73815440Sjkh int i; 73917362Sjkh static char _msg[40]; 7408549Sjkh 7418751Sjkh case '\014': /* ^L */ 74218619Sjkh clear_wins(); 74318619Sjkh break; 7448751Sjkh 74521698Sjkh case '\020': /* ^P */ 7468549Sjkh case KEY_UP: 7478549Sjkh case '-': 7488549Sjkh if (here != 0) 7498549Sjkh --here; 7508751Sjkh else 7518751Sjkh while (label_chunk_info[here + 1].c) 7528751Sjkh ++here; 7538549Sjkh break; 7548549Sjkh 75521698Sjkh case '\016': /* ^N */ 7568549Sjkh case KEY_DOWN: 7578549Sjkh case '+': 7588549Sjkh case '\r': 7598549Sjkh case '\n': 7608751Sjkh if (label_chunk_info[here + 1].c) 7618549Sjkh ++here; 7628751Sjkh else 7638751Sjkh here = 0; 7648549Sjkh break; 7658549Sjkh 7668549Sjkh case KEY_HOME: 7678549Sjkh here = 0; 7688549Sjkh break; 7698549Sjkh 7708549Sjkh case KEY_END: 7718751Sjkh while (label_chunk_info[here + 1].c) 7728549Sjkh ++here; 7738549Sjkh break; 7748549Sjkh 7758549Sjkh case KEY_F(1): 7768549Sjkh case '?': 77712661Speter systemDisplayHelp("partition"); 77818619Sjkh clear_wins(); 7798549Sjkh break; 7808549Sjkh 78110882Speter case 'A': 78210882Speter if (label_chunk_info[here].type != PART_SLICE) { 78315440Sjkh msg = "You can only do this in a disk slice (at top of screen)"; 78410882Speter break; 78510882Speter } 78610882Speter sz = space_free(label_chunk_info[here].c); 78717362Sjkh if (sz <= FS_MIN_SIZE) 78815440Sjkh msg = "Not enough free space to create a new partition in the slice"; 78915440Sjkh else { 79015440Sjkh struct chunk *tmp; 79115440Sjkh int mib[2]; 79215440Sjkh int physmem; 79315440Sjkh size_t size, swsize; 79415440Sjkh char *cp; 79517362Sjkh Chunk *rootdev, *swapdev, *usrdev, *vardev; 79612661Speter 79717368Sjkh (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev, &vardev); 79817362Sjkh if (!rootdev) { 79917362Sjkh cp = variable_get(VAR_ROOT_SIZE); 80017362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 80144601Sjkh (cp ? atoi(cp) : ROOT_DEFAULT_SIZE) * ONE_MEG, part, FS_BSDFFS, CHUNK_IS_ROOT); 80217362Sjkh if (!tmp) { 80317362Sjkh msgConfirm("Unable to create the root partition. Too big?"); 80418619Sjkh clear_wins(); 80517362Sjkh break; 80617362Sjkh } 80717362Sjkh tmp->private_data = new_part("/", TRUE, tmp->size); 80817362Sjkh tmp->private_free = safe_free; 80930345Sjkh record_label_chunks(devs, dev); 81015440Sjkh } 81117362Sjkh 81217362Sjkh if (!swapdev) { 81317362Sjkh cp = variable_get(VAR_SWAP_SIZE); 81417362Sjkh if (cp) 81517362Sjkh swsize = atoi(cp) * ONE_MEG; 81617362Sjkh else { 81717362Sjkh mib[0] = CTL_HW; 81817362Sjkh mib[1] = HW_PHYSMEM; 81917362Sjkh size = sizeof physmem; 82017362Sjkh sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 82117362Sjkh swsize = 16 * ONE_MEG + (physmem * 2 / 512); 82217362Sjkh } 82317362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 82417362Sjkh swsize, part, FS_SWAP, 0); 82517362Sjkh if (!tmp) { 82617362Sjkh msgConfirm("Unable to create the swap partition. Too big?"); 82718619Sjkh clear_wins(); 82817362Sjkh break; 82917362Sjkh } 83017362Sjkh tmp->private_data = 0; 83117362Sjkh tmp->private_free = safe_free; 83230345Sjkh record_label_chunks(devs, dev); 83315440Sjkh } 83417362Sjkh 83517362Sjkh if (!vardev) { 83617362Sjkh cp = variable_get(VAR_VAR_SIZE); 83737735Sjkh if (cp) 83837735Sjkh sz = atoi(cp) * ONE_MEG; 83937735Sjkh else 84037735Sjkh sz = variable_get(VAR_NO_USR) 84137735Sjkh ? space_free(label_chunk_info[here].c) 84237735Sjkh : VAR_MIN_SIZE * ONE_MEG; 84337735Sjkh 84417362Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, label_chunk_info[here].c, 84537735Sjkh sz, part, FS_BSDFFS, 0); 84617362Sjkh if (!tmp) { 84717362Sjkh msgConfirm("Less than %dMB free for /var - you will need to\n" 84817362Sjkh "partition your disk manually with a custom install!", 84917362Sjkh (cp ? atoi(cp) : VAR_MIN_SIZE)); 85018619Sjkh clear_wins(); 85117362Sjkh break; 85217362Sjkh } 85317362Sjkh tmp->private_data = new_part("/var", TRUE, tmp->size); 85417362Sjkh tmp->private_free = safe_free; 85530345Sjkh record_label_chunks(devs, dev); 85615440Sjkh } 85712661Speter 85837735Sjkh if (!usrdev && !variable_get(VAR_NO_USR)) { 85917362Sjkh cp = variable_get(VAR_USR_SIZE); 86017362Sjkh if (cp) 86117362Sjkh sz = atoi(cp) * ONE_MEG; 86217362Sjkh else 86317362Sjkh sz = space_free(label_chunk_info[here].c); 86429501Sjkh if (sz) { 86529501Sjkh if (sz < (USR_MIN_SIZE * ONE_MEG)) { 86629501Sjkh msgConfirm("Less than %dMB free for /usr - you will need to\n" 86729501Sjkh "partition your disk manually with a custom install!", USR_MIN_SIZE); 86829501Sjkh clear_wins(); 86929501Sjkh break; 87029501Sjkh } 87117362Sjkh 87229501Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 87329501Sjkh label_chunk_info[here].c, 87429501Sjkh sz, part, FS_BSDFFS, 0); 87529501Sjkh if (!tmp) { 87629501Sjkh msgConfirm("Unable to create the /usr partition. Not enough space?\n" 87729501Sjkh "You will need to partition your disk manually with a custom install!"); 87829501Sjkh clear_wins(); 87929501Sjkh break; 88029501Sjkh } 88129501Sjkh tmp->private_data = new_part("/usr", TRUE, tmp->size); 88229501Sjkh tmp->private_free = safe_free; 88330345Sjkh record_label_chunks(devs, dev); 88417362Sjkh } 88515440Sjkh } 88637735Sjkh 88715440Sjkh /* At this point, we're reasonably "labelled" */ 88818744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 88943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 89010882Speter } 89115440Sjkh break; 89210882Speter 8938549Sjkh case 'C': 8948549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 8958549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 8968549Sjkh break; 8978549Sjkh } 8988549Sjkh sz = space_free(label_chunk_info[here].c); 8998669Sphk if (sz <= FS_MIN_SIZE) { 90012661Speter msg = "Not enough space to create an additional FreeBSD partition"; 9018669Sphk break; 9028669Sphk } 90315440Sjkh else { 90418744Sjkh char *val; 9058702Sjkh int size; 9068702Sjkh struct chunk *tmp; 9078820Sjkh char osize[80]; 9088702Sjkh u_long flags = 0; 9098549Sjkh 9108820Sjkh sprintf(osize, "%d", sz); 91118619Sjkh DialogX = 3; 91218621Sjkh DialogY = 2; 91318619Sjkh val = msgGetInput(osize, 91418619Sjkh "Please specify the partition size in blocks or append a trailing M for\n" 91518619Sjkh "megabytes or C for cylinders. %d blocks (%dMB) are free.", 91618619Sjkh sz, sz / ONE_MEG); 91718619Sjkh DialogX = DialogY = 0; 91818619Sjkh if (!val || (size = strtol(val, &cp, 0)) <= 0) { 91918619Sjkh clear_wins(); 9208702Sjkh break; 92118619Sjkh } 9228549Sjkh 9238751Sjkh if (*cp) { 9248751Sjkh if (toupper(*cp) == 'M') 9258751Sjkh size *= ONE_MEG; 9268751Sjkh else if (toupper(*cp) == 'C') 9278751Sjkh size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 9288751Sjkh } 9298820Sjkh if (size <= FS_MIN_SIZE) { 9308820Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 93118619Sjkh clear_wins(); 9328820Sjkh break; 9338820Sjkh } 9348702Sjkh type = get_partition_type(); 93518619Sjkh if (type == PART_NONE) { 93618619Sjkh clear_wins(); 93718619Sjkh beep(); 9388669Sphk break; 93918619Sjkh } 9408669Sphk 9418702Sjkh if (type == PART_FILESYSTEM) { 94218619Sjkh if ((p = get_mountpoint(NULL)) == NULL) { 94318619Sjkh clear_wins(); 94418619Sjkh beep(); 9458702Sjkh break; 94618619Sjkh } 9478702Sjkh else if (!strcmp(p->mountpoint, "/")) 9488702Sjkh flags |= CHUNK_IS_ROOT; 9498702Sjkh else 9508702Sjkh flags &= ~CHUNK_IS_ROOT; 95118619Sjkh } 95218619Sjkh else 9538702Sjkh p = NULL; 9548702Sjkh 9558702Sjkh if ((flags & CHUNK_IS_ROOT)) { 9568702Sjkh if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 95712661Speter msgConfirm("This region cannot be used for your root partition as the\n" 95812661Speter "FreeBSD boot code cannot deal with a root partition created\n" 95912661Speter "in that location. Please choose another location or smaller\n" 96012661Speter "size for your root partition and try again!"); 96118619Sjkh clear_wins(); 9628702Sjkh break; 9638702Sjkh } 96412661Speter if (size < (ROOT_MIN_SIZE * ONE_MEG)) { 96512661Speter msgConfirm("Warning: This is smaller than the recommended size for a\n" 96612661Speter "root partition. For a variety of reasons, root\n" 96712661Speter "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 96812661Speter } 9698672Sjkh } 9708751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 9718702Sjkh label_chunk_info[here].c, 9728702Sjkh size, part, 9738702Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 9748702Sjkh flags); 9758702Sjkh if (!tmp) { 9768702Sjkh msgConfirm("Unable to create the partition. Too big?"); 97718619Sjkh clear_wins(); 9788672Sjkh break; 9798672Sjkh } 9808702Sjkh if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 98112661Speter msgConfirm("This region cannot be used for your root partition as it starts\n" 98212661Speter "or extends past the 1024'th cylinder mark and is thus a\n" 98312661Speter "poor location to boot from. Please choose another\n" 98412661Speter "location (or smaller size) for your root partition and try again!"); 9858751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, tmp); 98618619Sjkh clear_wins(); 9878669Sphk break; 9888702Sjkh } 9898702Sjkh if (type != PART_SWAP) { 9908669Sphk /* This is needed to tell the newfs -u about the size */ 99114793Sjoerg tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size); 9928669Sphk safe_free(p); 99315355Sjkh } 99415355Sjkh else 99514793Sjoerg tmp->private_data = p; 9968702Sjkh tmp->private_free = safe_free; 99718744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 99843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 99930345Sjkh record_label_chunks(devs, dev); 100018619Sjkh clear_wins(); 100129249Sjkh /*** This is where we assign focus to new label so it shows ***/ 100229249Sjkh { 100329249Sjkh int i; 100429249Sjkh label_focus = -1; 100529249Sjkh for (i = 0; label_chunk_info[i].c; ++i) { 100629249Sjkh if (label_chunk_info[i].c == tmp) { 100729249Sjkh label_focus = i; 100829249Sjkh break; 100929249Sjkh } 101029249Sjkh } 101129249Sjkh if (label_focus == -1) 101229249Sjkh label_focus = i - 1; 101329249Sjkh } 10148549Sjkh } 10158549Sjkh break; 10168549Sjkh 101717397Sjkh case KEY_DC: 10188549Sjkh case 'D': /* delete */ 10198549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 10208549Sjkh msg = MSG_NOT_APPLICABLE; 10218549Sjkh break; 10228549Sjkh } 10238549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 10248705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 10258549Sjkh break; 10268549Sjkh } 10278751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 102818744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 102943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 103030345Sjkh record_label_chunks(devs, dev); 10318549Sjkh break; 10328549Sjkh 10338549Sjkh case 'M': /* mount */ 10348549Sjkh switch(label_chunk_info[here].type) { 10358549Sjkh case PART_SLICE: 10368549Sjkh msg = MSG_NOT_APPLICABLE; 10378549Sjkh break; 10388549Sjkh 10398549Sjkh case PART_SWAP: 10408549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 10418549Sjkh break; 10428549Sjkh 10438556Sjkh case PART_FAT: 10448549Sjkh case PART_FILESYSTEM: 104514793Sjoerg oldp = label_chunk_info[here].c->private_data; 10468589Sjkh p = get_mountpoint(label_chunk_info[here].c); 10478549Sjkh if (p) { 10489202Srgrimes if (!oldp) 10499202Srgrimes p->newfs = FALSE; 10508722Sjkh if (label_chunk_info[here].type == PART_FAT 10518722Sjkh && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 10528722Sjkh || !strcmp(p->mountpoint, "/var"))) { 10538722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 10548722Sjkh strcpy(p->mountpoint, "/bogus"); 10558722Sjkh } 10568549Sjkh } 105718744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 105843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 105930345Sjkh record_label_chunks(devs, dev); 106018636Sjkh clear_wins(); 10618549Sjkh break; 10628549Sjkh 10638549Sjkh default: 10648549Sjkh msgFatal("Bogus partition under cursor???"); 10658549Sjkh break; 10668549Sjkh } 10678549Sjkh break; 10688549Sjkh 10698549Sjkh case 'N': /* Set newfs options */ 107014793Sjoerg if (label_chunk_info[here].c->private_data && 107114793Sjoerg ((PartInfo *)label_chunk_info[here].c->private_data)->newfs) 107214793Sjoerg getNewfsCmd(label_chunk_info[here].c->private_data); 10738549Sjkh else 10748549Sjkh msg = MSG_NOT_APPLICABLE; 107518636Sjkh clear_wins(); 10768549Sjkh break; 10778549Sjkh 10788549Sjkh case 'T': /* Toggle newfs state */ 10799202Srgrimes if (label_chunk_info[here].type == PART_FILESYSTEM) { 108023729Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 108123729Sjkh label_chunk_info[here].c->private_data = 108223729Sjkh new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size); 108323729Sjkh safe_free(pi); 108423729Sjkh label_chunk_info[here].c->private_free = safe_free; 108523729Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 108643685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 108718619Sjkh } 10888549Sjkh else 10898549Sjkh msg = MSG_NOT_APPLICABLE; 10908549Sjkh break; 10918549Sjkh 10928820Sjkh case 'U': 109312661Speter clear(); 109418744Sjkh if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 109518744Sjkh msgConfirm("You've already written out your changes -\n" 109618744Sjkh "it's too late to undo!"); 109718744Sjkh } 109818744Sjkh else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 109918744Sjkh variable_unset(DISK_PARTITIONED); 110018744Sjkh variable_unset(DISK_LABELLED); 110118744Sjkh for (i = 0; devs[i]; i++) { 110218744Sjkh Disk *d; 110312661Speter 110418744Sjkh if (!devs[i]->enabled) 110518744Sjkh continue; 110618744Sjkh else if ((d = Open_Disk(devs[i]->name)) != NULL) { 110718744Sjkh Free_Disk(devs[i]->private); 110818744Sjkh devs[i]->private = d; 110930345Sjkh diskPartition(devs[i]); 111018744Sjkh } 11118824Sjkh } 111230345Sjkh record_label_chunks(devs, dev); 11138824Sjkh } 111418636Sjkh clear_wins(); 11158824Sjkh break; 11168820Sjkh 11178549Sjkh case 'W': 111818744Sjkh if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 111918744Sjkh msgConfirm("You've already written out your changes - if you\n" 112018744Sjkh "wish to overwrite them, you'll have to start this\n" 112118744Sjkh "procedure again from the beginning."); 112218744Sjkh } 112318744Sjkh else if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 112418687Sjkh "installation. If you are installing FreeBSD for the first time\n" 112518687Sjkh "then you should simply type Q when you're finished here and your\n" 112618687Sjkh "changes will be committed in one batch automatically at the end of\n" 112718687Sjkh "these questions.\n\n" 112818687Sjkh "Are you absolutely sure you want to do this now?")) { 112943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 113012661Speter diskLabelCommit(NULL); 113112661Speter } 113218636Sjkh clear_wins(); 113310882Speter break; 113410882Speter 113510882Speter case '|': 113612661Speter if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\n" 113712661Speter "This is an entirely undocumented feature which you are not\n" 113812661Speter "expected to understand!")) { 11398549Sjkh int i; 11408549Sjkh Device **devs; 11418549Sjkh 11428549Sjkh dialog_clear(); 11438549Sjkh end_dialog(); 11448549Sjkh DialogActive = FALSE; 11458549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 11468549Sjkh if (!devs) { 114712661Speter msgConfirm("Can't find any disk devices!"); 11488549Sjkh break; 11498549Sjkh } 11508668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 11518613Sjkh if (devs[i]->enabled) 11528613Sjkh slice_wizard(((Disk *)devs[i]->private)); 11538613Sjkh } 115418744Sjkh if (((cp = variable_get(DISK_LABELLED)) == NULL) || (strcmp(cp, "written"))) 115543685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 11568665Sphk DialogActive = TRUE; 115730345Sjkh record_label_chunks(devs, dev); 115818636Sjkh clear_wins(); 11598549Sjkh } 11608549Sjkh else 11618549Sjkh msg = "A most prudent choice!"; 11628549Sjkh break; 11638549Sjkh 116421698Sjkh case '\033': /* ESC */ 11659202Srgrimes case 'Q': 11668549Sjkh labeling = FALSE; 11678549Sjkh break; 11688549Sjkh 11698549Sjkh default: 11708549Sjkh beep(); 117117362Sjkh sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 117217362Sjkh msg = _msg; 11738549Sjkh break; 11748549Sjkh } 117529633Sjkh if (label_chunk_info[here].type == PART_SLICE) 117629633Sjkh pslice_focus = here; 117729633Sjkh else 117829633Sjkh label_focus = here; 11798549Sjkh } 118054587Sjkh restorescr(w); 118154587Sjkh return DITEM_SUCCESS; 11828549Sjkh} 118326456Sjkh 118426456Sjkhstatic int 118530345SjkhdiskLabelNonInteractive(Device *dev) 118626456Sjkh{ 118726456Sjkh char *cp; 118826456Sjkh PartType type; 118926456Sjkh PartInfo *p; 119026456Sjkh u_long flags = 0; 119126456Sjkh int i, status; 119226456Sjkh Device **devs; 119326456Sjkh Disk *d; 119454587Sjkh 119526456Sjkh status = DITEM_SUCCESS; 119626456Sjkh cp = variable_get(VAR_DISK); 119726456Sjkh if (!cp) { 119826456Sjkh msgConfirm("diskLabel: No disk selected - can't label automatically."); 119926456Sjkh return DITEM_FAILURE; 120026456Sjkh } 120126456Sjkh devs = deviceFind(cp, DEVICE_TYPE_DISK); 120226456Sjkh if (!devs) { 120326456Sjkh msgConfirm("diskLabel: No disk device %s found!", cp); 120426456Sjkh return DITEM_FAILURE; 120526456Sjkh } 120630345Sjkh if (dev) 120730345Sjkh d = dev->private; 120830345Sjkh else 120930345Sjkh d = devs[0]->private; 121042386Sjkh#ifdef __alpha__ 121143392Sjkh maybe_dedicate(d); 121242386Sjkh#endif 121330345Sjkh record_label_chunks(devs, dev); 121426456Sjkh for (i = 0; label_chunk_info[i].c; i++) { 121526456Sjkh Chunk *c1 = label_chunk_info[i].c; 121626456Sjkh 121726456Sjkh if (label_chunk_info[i].type == PART_SLICE) { 121828075Sjkh char name[512]; 121928075Sjkh int entries = 1; 122026456Sjkh 122128075Sjkh while (entries) { 122228075Sjkh snprintf(name, sizeof name, "%s-%d", c1->name, entries); 122328075Sjkh if ((cp = variable_get(name)) != NULL) { 122428075Sjkh int sz; 122528075Sjkh char typ[10], mpoint[50]; 122626456Sjkh 122728075Sjkh if (sscanf(cp, "%s %d %s", typ, &sz, mpoint) != 3) { 122828075Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 122926456Sjkh status = DITEM_FAILURE; 123026456Sjkh continue; 123126456Sjkh } 123226456Sjkh else { 123328075Sjkh Chunk *tmp; 123428075Sjkh 123528075Sjkh if (!strcmp(typ, "swap")) { 123628075Sjkh type = PART_SWAP; 123728075Sjkh strcpy(mpoint, "SWAP"); 123828075Sjkh } 123928075Sjkh else { 124028075Sjkh type = PART_FILESYSTEM; 124128075Sjkh if (!strcmp(mpoint, "/")) 124228075Sjkh flags |= CHUNK_IS_ROOT; 124333132Sjkh else 124433132Sjkh flags &= ~CHUNK_IS_ROOT; 124528075Sjkh } 124628075Sjkh if (!sz) 124728075Sjkh sz = space_free(c1); 124828075Sjkh if (sz > space_free(c1)) { 124928075Sjkh msgConfirm("Not enough free space to create partition: %s", mpoint); 125028075Sjkh status = DITEM_FAILURE; 125128075Sjkh continue; 125228075Sjkh } 125328075Sjkh if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 125428075Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 125528075Sjkh msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 125628075Sjkh status = DITEM_FAILURE; 125728075Sjkh break; 125828075Sjkh } 125928075Sjkh else { 126028075Sjkh tmp->private_data = new_part(mpoint, TRUE, sz); 126128075Sjkh tmp->private_free = safe_free; 126228075Sjkh status = DITEM_SUCCESS; 126328075Sjkh } 126426456Sjkh } 126528075Sjkh entries++; 126626456Sjkh } 126728075Sjkh else { 126828075Sjkh /* No more matches, leave the loop */ 126928075Sjkh entries = 0; 127028075Sjkh } 127126456Sjkh } 127226456Sjkh } 127326456Sjkh else { 127428075Sjkh /* Must be something we can set a mountpoint for */ 127526456Sjkh cp = variable_get(c1->name); 127626456Sjkh if (cp) { 127728075Sjkh char mpoint[50], do_newfs[8]; 127826456Sjkh Boolean newfs = FALSE; 127926456Sjkh 128028075Sjkh do_newfs[0] = '\0'; 128128075Sjkh if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 128226456Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 128326456Sjkh status = DITEM_FAILURE; 128426456Sjkh continue; 128526456Sjkh } 128628075Sjkh newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 128726456Sjkh if (c1->private_data) { 128826456Sjkh p = c1->private_data; 128926456Sjkh p->newfs = newfs; 129026456Sjkh strcpy(p->mountpoint, mpoint); 129126456Sjkh } 129226456Sjkh else { 129326456Sjkh c1->private_data = new_part(mpoint, newfs, 0); 129426456Sjkh c1->private_free = safe_free; 129526456Sjkh } 129626456Sjkh if (!strcmp(mpoint, "/")) 129726456Sjkh c1->flags |= CHUNK_IS_ROOT; 129826456Sjkh else 129926456Sjkh c1->flags &= ~CHUNK_IS_ROOT; 130026456Sjkh } 130126456Sjkh } 130226456Sjkh } 130326456Sjkh if (status == DITEM_SUCCESS) 130443685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 130526456Sjkh return status; 130626456Sjkh} 1307