label.c revision 8810
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 * 78810Sjkh * $Id: label.c,v 1.26 1995/05/26 11:21:46 jkh Exp $ 88549Sjkh * 98549Sjkh * Copyright (c) 1995 108549Sjkh * Jordan Hubbard. All rights reserved. 118549Sjkh * 128549Sjkh * Redistribution and use in source and binary forms, with or without 138549Sjkh * modification, are permitted provided that the following conditions 148549Sjkh * are met: 158549Sjkh * 1. Redistributions of source code must retain the above copyright 168549Sjkh * notice, this list of conditions and the following disclaimer, 178549Sjkh * 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 * 3. All advertising materials mentioning features or use of this software 238549Sjkh * must display the following acknowledgement: 248549Sjkh * This product includes software developed by Jordan Hubbard 258549Sjkh * for the FreeBSD Project. 268549Sjkh * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 278549Sjkh * endorse or promote products derived from this software without specific 288549Sjkh * prior written permission. 298549Sjkh * 308549Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 318549Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 328549Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 338549Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 348549Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 358549Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 368549Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 378549Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 388549Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 398549Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 408549Sjkh * SUCH DAMAGE. 418549Sjkh * 428549Sjkh */ 438549Sjkh 448549Sjkh#include "sysinstall.h" 458549Sjkh#include <ctype.h> 468549Sjkh#include <sys/disklabel.h> 478549Sjkh 488549Sjkh/* 498549Sjkh * Everything to do with editing the contents of disk labels. 508549Sjkh */ 518549Sjkh 528549Sjkh/* A nice message we use a lot in the disklabel editor */ 538549Sjkh#define MSG_NOT_APPLICABLE "That option is not applicable here" 548549Sjkh 558549Sjkh/* Where to start printing the freebsd slices */ 568549Sjkh#define CHUNK_SLICE_START_ROW 2 578622Sjkh#define CHUNK_PART_START_ROW 11 588549Sjkh 598702Sjkh/* One MB worth of blocks */ 608702Sjkh#define ONE_MEG 2048 618702Sjkh 628549Sjkh/* The smallest filesystem we're willing to create */ 638702Sjkh#define FS_MIN_SIZE ONE_MEG 648549Sjkh 658672Sjkh/* The smallest root filesystem we're willing to create */ 668702Sjkh#define ROOT_MIN_SIZE (20 * ONE_MEG) 678549Sjkh 688549Sjkh/* All the chunks currently displayed on the screen */ 698549Sjkhstatic struct { 708549Sjkh struct chunk *c; 718549Sjkh PartType type; 728549Sjkh} label_chunk_info[MAX_CHUNKS + 1]; 738549Sjkhstatic int here; 748549Sjkh 758549Sjkh/* See if we're already using a desired partition name */ 768549Sjkhstatic Boolean 778549Sjkhcheck_conflict(char *name) 788549Sjkh{ 798549Sjkh int i; 808549Sjkh 818751Sjkh for (i = 0; label_chunk_info[i].c; i++) 828549Sjkh if (label_chunk_info[i].type == PART_FILESYSTEM 838549Sjkh && label_chunk_info[i].c->private 848549Sjkh && !strcmp(((PartInfo *)label_chunk_info[i].c->private)->mountpoint, name)) 858549Sjkh return TRUE; 868549Sjkh return FALSE; 878549Sjkh} 888549Sjkh 898549Sjkh/* How much space is in this FreeBSD slice? */ 908549Sjkhstatic int 918549Sjkhspace_free(struct chunk *c) 928549Sjkh{ 938549Sjkh struct chunk *c1 = c->part; 948549Sjkh int sz = c->size; 958549Sjkh 968549Sjkh while (c1) { 978549Sjkh if (c1->type != unused) 988549Sjkh sz -= c1->size; 998549Sjkh c1 = c1->next; 1008549Sjkh } 1018549Sjkh if (sz < 0) 1028549Sjkh msgFatal("Partitions are larger than actual chunk??"); 1038549Sjkh return sz; 1048549Sjkh} 1058549Sjkh 1068549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 1078549Sjkhstatic void 1088549Sjkhrecord_label_chunks() 1098549Sjkh{ 1108549Sjkh int i, j, p; 1118549Sjkh struct chunk *c1, *c2; 1128549Sjkh Device **devs; 1138556Sjkh Disk *d; 1148549Sjkh 1158549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 1168549Sjkh if (!devs) { 1178549Sjkh msgConfirm("No disks found!"); 1188549Sjkh return; 1198549Sjkh } 1208549Sjkh 1218549Sjkh j = p = 0; 1228556Sjkh /* First buzz through and pick up the FreeBSD slices */ 1238549Sjkh for (i = 0; devs[i]; i++) { 1248556Sjkh if (!devs[i]->enabled) 1258556Sjkh continue; 1268556Sjkh d = (Disk *)devs[i]->private; 1278556Sjkh if (!d->chunks) 1288556Sjkh msgFatal("No chunk list found for %s!", d->name); 1298549Sjkh 1308556Sjkh /* Put the slice entries first */ 1318556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 1328549Sjkh if (c1->type == freebsd) { 1338549Sjkh label_chunk_info[j].type = PART_SLICE; 1348549Sjkh label_chunk_info[j].c = c1; 1358549Sjkh ++j; 1368549Sjkh } 1378549Sjkh } 1388549Sjkh } 1398556Sjkh /* Now run through again and get the FreeBSD partition entries */ 1408556Sjkh for (i = 0; devs[i]; i++) { 1418556Sjkh if (!devs[i]->enabled) 1428556Sjkh continue; 1438556Sjkh d = (Disk *)devs[i]->private; 1448549Sjkh /* Then buzz through and pick up the partitions */ 1458556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 1468549Sjkh if (c1->type == freebsd) { 1478549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 1488549Sjkh if (c2->type == part) { 1498549Sjkh if (c2->subtype == FS_SWAP) 1508549Sjkh label_chunk_info[j].type = PART_SWAP; 1518549Sjkh else 1528549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 1538549Sjkh label_chunk_info[j].c = c2; 1548549Sjkh ++j; 1558549Sjkh } 1568549Sjkh } 1578549Sjkh } 1588549Sjkh else if (c1->type == fat) { 1598549Sjkh label_chunk_info[j].type = PART_FAT; 1608549Sjkh label_chunk_info[j].c = c1; 1618702Sjkh ++j; 1628549Sjkh } 1638549Sjkh } 1648549Sjkh } 1658549Sjkh label_chunk_info[j].c = NULL; 1668549Sjkh if (here >= j) 1678549Sjkh here = j ? j - 1 : 0; 1688549Sjkh} 1698549Sjkh 1708549Sjkh/* A new partition entry */ 1718549Sjkhstatic PartInfo * 1728665Sphknew_part(char *mpoint, Boolean newfs, u_long size) 1738549Sjkh{ 1748549Sjkh PartInfo *ret; 1758666Sphk u_long target,divisor; 1768549Sjkh 1778549Sjkh ret = (PartInfo *)safe_malloc(sizeof(PartInfo)); 1788549Sjkh strncpy(ret->mountpoint, mpoint, FILENAME_MAX); 1798549Sjkh strcpy(ret->newfs_cmd, "newfs"); 1808666Sphk ret->newfs = newfs; 1818669Sphk if (!size) 1828669Sphk return ret; 1838666Sphk for(target = size; target; target--) { 1848666Sphk for(divisor = 4096 ; divisor > 1023; divisor--) { 1858666Sphk if (!(target % divisor)) { 1868666Sphk sprintf(ret->newfs_cmd+strlen(ret->newfs_cmd), 1878666Sphk " -u %ld",divisor); 1888666Sphk return ret; 1898666Sphk } 1908665Sphk } 1918665Sphk } 1928549Sjkh return ret; 1938549Sjkh} 1948549Sjkh 1958549Sjkh/* Get the mountpoint for a partition and save it away */ 1968549SjkhPartInfo * 1978589Sjkhget_mountpoint(struct chunk *old) 1988549Sjkh{ 1998549Sjkh char *val; 2008549Sjkh PartInfo *tmp; 2018549Sjkh 2028810Sjkh if (old && old->private) 2038810Sjkh tmp = old->private; 2048810Sjkh else 2058810Sjkh tmp = NULL; 2068810Sjkh val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition"); 2078764Sjkh if (!val || !*val) { 2088751Sjkh if (!old) 2098751Sjkh return NULL; 2108751Sjkh else { 2118751Sjkh free(old->private); 2128751Sjkh old->private = NULL; 2138751Sjkh } 2148669Sphk return NULL; 2158751Sjkh } 2168669Sphk 2178669Sphk /* Is it just the same value? */ 2188810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 2198669Sphk return NULL; 2208810Sjkh 2218810Sjkh /* Did we use it already? */ 2228669Sphk if (check_conflict(val)) { 2238669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 2248669Sphk return NULL; 2258549Sjkh } 2268810Sjkh 2278810Sjkh /* Is it bogus? */ 2288669Sphk if (*val != '/') { 2298669Sphk msgConfirm("Mount point must start with a / character"); 2308669Sphk return NULL; 2318669Sphk } 2328810Sjkh 2338810Sjkh /* Is it going to be mounted on root? */ 2348669Sphk if (!strcmp(val, "/")) { 2358669Sphk if (old) 2368669Sphk old->flags |= CHUNK_IS_ROOT; 2378810Sjkh } 2388810Sjkh else if (old) 2398669Sphk old->flags &= ~CHUNK_IS_ROOT; 2408810Sjkh 2418810Sjkh safe_free(tmp); 2428669Sphk tmp = new_part(val, TRUE, 0); 2438669Sphk if (old) { 2448669Sphk old->private = tmp; 2458669Sphk old->private_free = safe_free; 2468669Sphk } 2478669Sphk return tmp; 2488549Sjkh} 2498549Sjkh 2508549Sjkh/* Get the type of the new partiton */ 2518549Sjkhstatic PartType 2528549Sjkhget_partition_type(void) 2538549Sjkh{ 2548549Sjkh char selection[20]; 2558669Sphk int i; 2568669Sphk 2578549Sjkh static unsigned char *fs_types[] = { 2588549Sjkh "FS", 2598549Sjkh "A file system", 2608549Sjkh "Swap", 2618549Sjkh "A swap partition.", 2628549Sjkh }; 2638669Sphk i = dialog_menu("Please choose a partition type", 2648669Sphk "If you want to use this partition for swap space, select Swap.\nIf you want to put a filesystem on it, choose FS.", -1, -1, 2, 2, fs_types, selection, NULL, NULL); 2658669Sphk if (!i) { 2668549Sjkh if (!strcmp(selection, "FS")) 2678549Sjkh return PART_FILESYSTEM; 2688549Sjkh else if (!strcmp(selection, "Swap")) 2698549Sjkh return PART_SWAP; 2708549Sjkh } 2718549Sjkh return PART_NONE; 2728549Sjkh} 2738549Sjkh 2748549Sjkh/* If the user wants a special newfs command for this, set it */ 2758549Sjkhstatic void 2768549SjkhgetNewfsCmd(PartInfo *p) 2778549Sjkh{ 2788549Sjkh char *val; 2798549Sjkh 2808549Sjkh val = msgGetInput(p->newfs_cmd, 2818549Sjkh "Please enter the newfs command and options you'd like to use in\ncreating this file system."); 2828549Sjkh if (val) 2838549Sjkh strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX); 2848549Sjkh} 2858549Sjkh 2868549Sjkh 2878549Sjkh#define MAX_MOUNT_NAME 12 2888549Sjkh 2898549Sjkh#define PART_PART_COL 0 2908549Sjkh#define PART_MOUNT_COL 8 2918549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 2928549Sjkh#define PART_NEWFS_COL (PART_SIZE_COL + 7) 2938549Sjkh#define PART_OFF 38 2948549Sjkh 2958549Sjkh/* How many mounted partitions to display in column before going to next */ 2968622Sjkh#define CHUNK_COLUMN_MAX 5 2978549Sjkh 2988549Sjkh/* stick this all up on the screen */ 2998549Sjkhstatic void 3008549Sjkhprint_label_chunks(void) 3018549Sjkh{ 3028549Sjkh int i, j, srow, prow, pcol; 3038549Sjkh int sz; 3048549Sjkh 3058549Sjkh attrset(A_REVERSE); 3068549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 3078669Sphk clrtobot(); 3088549Sjkh attrset(A_NORMAL); 3098549Sjkh 3108549Sjkh for (i = 0; i < 2; i++) { 3118622Sjkh mvaddstr(CHUNK_PART_START_ROW - 2, PART_PART_COL + (i * PART_OFF), "Part"); 3128622Sjkh mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF), "----"); 3138549Sjkh 3148622Sjkh mvaddstr(CHUNK_PART_START_ROW - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 3158622Sjkh mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 3168549Sjkh 3178622Sjkh mvaddstr(CHUNK_PART_START_ROW - 2, PART_SIZE_COL + (i * PART_OFF) + 2, "Size"); 3188622Sjkh mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2, "----"); 3198549Sjkh 3208622Sjkh mvaddstr(CHUNK_PART_START_ROW - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 3218622Sjkh mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 3228549Sjkh } 3238549Sjkh srow = CHUNK_SLICE_START_ROW; 3248549Sjkh prow = CHUNK_PART_START_ROW; 3258549Sjkh pcol = 0; 3268549Sjkh 3278751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 3288549Sjkh if (i == here) 3298549Sjkh attrset(A_REVERSE); 3308549Sjkh /* Is it a slice entry displayed at the top? */ 3318549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 3328549Sjkh sz = space_free(label_chunk_info[i].c); 3338751Sjkh mvprintw(srow++, 0, "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)", 3348751Sjkh label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name, sz, (sz / ONE_MEG)); 3358549Sjkh } 3368549Sjkh /* Otherwise it's a DOS, swap or filesystem entry, at the bottom */ 3378549Sjkh else { 3388549Sjkh char onestr[PART_OFF], num[10], *mountpoint, *newfs; 3398549Sjkh 3408549Sjkh /* 3418549Sjkh * We copy this into a blank-padded string so that it looks like 3428549Sjkh * a solid bar in reverse-video 3438549Sjkh */ 3448549Sjkh memset(onestr, ' ', PART_OFF - 1); 3458549Sjkh onestr[PART_OFF - 1] = '\0'; 3468549Sjkh /* Go for two columns */ 3478549Sjkh if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) { 3488549Sjkh pcol = PART_OFF; 3498549Sjkh prow = CHUNK_PART_START_ROW; 3508549Sjkh } 3518705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 3528549Sjkh /* If it's a filesystem, display the mountpoint */ 3538705Sjkh if (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT) { 3548549Sjkh if (label_chunk_info[i].c->private == NULL) { 3558549Sjkh static int mnt = 0; 3568549Sjkh char foo[10]; 3578549Sjkh 3588549Sjkh /* 3598549Sjkh * Hmm! A partition that must have already been here. 3608549Sjkh * Fill in a fake mountpoint and register it 3618549Sjkh */ 3628549Sjkh sprintf(foo, "/mnt%d", mnt++); 3638705Sjkh label_chunk_info[i].c->private = new_part(foo, FALSE, label_chunk_info[i].c->size); 3648549Sjkh label_chunk_info[i].c->private_free = safe_free; 3658549Sjkh } 3668549Sjkh mountpoint = ((PartInfo *)label_chunk_info[i].c->private)->mountpoint; 3678705Sjkh if (label_chunk_info[i].type == PART_FAT) 3688705Sjkh newfs = "DOS"; 3698705Sjkh else 3708705Sjkh newfs = ((PartInfo *)label_chunk_info[i].c->private)->newfs ? "Y" : "N"; 3718549Sjkh } 3728549Sjkh else if (label_chunk_info[i].type == PART_SWAP) { 3738549Sjkh mountpoint = "swap"; 3748549Sjkh newfs = " "; 3758549Sjkh } 3768549Sjkh else { 3778705Sjkh mountpoint = "<NONE>"; 3788549Sjkh newfs = "*"; 3798549Sjkh } 3808549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 3818549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 3828764Sjkh snprintf(num, 10, "%4ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0); 3838549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 3848549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 3858549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 3868549Sjkh mvaddstr(prow, pcol, onestr); 3878549Sjkh ++prow; 3888549Sjkh } 3898549Sjkh if (i == here) 3908549Sjkh attrset(A_NORMAL); 3918549Sjkh } 3928549Sjkh} 3938549Sjkh 3948549Sjkhstatic void 3958549Sjkhprint_command_summary() 3968549Sjkh{ 3978549Sjkh mvprintw(17, 0, 3988549Sjkh "The following commands are valid here (upper or lower case):"); 3998549Sjkh mvprintw(19, 0, "C = Create Partition D = Delete Partition M = Mount Partition"); 4008556Sjkh mvprintw(20, 0, "N = Newfs Options T = Toggle Newfs ESC = Exit this screen"); 4018549Sjkh mvprintw(21, 0, "The default target will be displayed in "); 4028549Sjkh 4038549Sjkh attrset(A_REVERSE); 4048751Sjkh addstr("reverse"); 4058549Sjkh attrset(A_NORMAL); 4068751Sjkh addstr(" video."); 4078549Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to move."); 4088549Sjkh move(0, 0); 4098549Sjkh} 4108549Sjkh 4118576Sjkhint 4128549SjkhdiskLabelEditor(char *str) 4138549Sjkh{ 4148549Sjkh int sz, key = 0; 4158549Sjkh Boolean labeling; 4168549Sjkh char *msg = NULL; 4178549Sjkh PartInfo *p; 4188549Sjkh PartType type; 4198549Sjkh 4208549Sjkh labeling = TRUE; 4218549Sjkh keypad(stdscr, TRUE); 4228549Sjkh record_label_chunks(); 4238549Sjkh 4248576Sjkh if (!getenv(DISK_PARTITIONED)) { 4258576Sjkh msgConfirm("You need to partition your disk(s) before you can assign disk labels."); 4268576Sjkh return 0; 4278576Sjkh } 4288702Sjkh dialog_clear(); clear(); 4298549Sjkh while (labeling) { 4308702Sjkh clear(); 4318549Sjkh print_label_chunks(); 4328549Sjkh print_command_summary(); 4338549Sjkh if (msg) { 4348549Sjkh attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL); 4358549Sjkh beep(); 4368549Sjkh msg = NULL; 4378549Sjkh } 4388549Sjkh refresh(); 4398549Sjkh key = toupper(getch()); 4408549Sjkh switch (key) { 4418549Sjkh 4428751Sjkh case '\014': /* ^L */ 4438751Sjkh continue; 4448751Sjkh 4458549Sjkh case KEY_UP: 4468549Sjkh case '-': 4478549Sjkh if (here != 0) 4488549Sjkh --here; 4498751Sjkh else 4508751Sjkh while (label_chunk_info[here + 1].c) 4518751Sjkh ++here; 4528549Sjkh break; 4538549Sjkh 4548549Sjkh case KEY_DOWN: 4558549Sjkh case '+': 4568549Sjkh case '\r': 4578549Sjkh case '\n': 4588751Sjkh if (label_chunk_info[here + 1].c) 4598549Sjkh ++here; 4608751Sjkh else 4618751Sjkh here = 0; 4628549Sjkh break; 4638549Sjkh 4648549Sjkh case KEY_HOME: 4658549Sjkh here = 0; 4668549Sjkh break; 4678549Sjkh 4688549Sjkh case KEY_END: 4698751Sjkh while (label_chunk_info[here + 1].c) 4708549Sjkh ++here; 4718549Sjkh break; 4728549Sjkh 4738549Sjkh case KEY_F(1): 4748549Sjkh case '?': 4758549Sjkh systemDisplayFile("disklabel.hlp"); 4768549Sjkh break; 4778549Sjkh 4788549Sjkh case 'C': 4798549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 4808549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 4818549Sjkh break; 4828549Sjkh } 4838549Sjkh sz = space_free(label_chunk_info[here].c); 4848669Sphk if (sz <= FS_MIN_SIZE) { 4858549Sjkh msg = "Not enough space to create additional FreeBSD partition"; 4868669Sphk break; 4878669Sphk } 4888669Sphk { 4898705Sjkh char *val, *cp; 4908702Sjkh int size; 4918702Sjkh struct chunk *tmp; 4928702Sjkh u_long flags = 0; 4938549Sjkh 4948751Sjkh val = msgGetInput(NULL, "Please specify the size for new FreeBSD partition in blocks, or\nappend a trailing `M' for megabytes (e.g. 20M), `C' for cylinders\nor `%%' for a percentage of remaining space.\n\nSpace free is %d blocks (%dMB)", sz, sz / ONE_MEG); 4958702Sjkh if (!val || (size = strtol(val, &cp, 0)) <= 0) 4968702Sjkh break; 4978549Sjkh 4988702Sjkh if (sz <= FS_MIN_SIZE) { 4998702Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 5008702Sjkh break; 5018702Sjkh } 5028751Sjkh if (*cp) { 5038751Sjkh if (toupper(*cp) == 'M') 5048751Sjkh size *= ONE_MEG; 5058751Sjkh else if (toupper(*cp) == 'C') 5068751Sjkh size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 5078764Sjkh else if (*cp == '%') { 5088764Sjkh float fsz, fsize; 5098764Sjkh 5108764Sjkh fsz = (float)sz; 5118764Sjkh fsize = (float)size; 5128764Sjkh fsize *= 0.10; 5138764Sjkh fsz *= fsize; 5148764Sjkh size = (int)fsz; 5158764Sjkh } 5168751Sjkh } 5178702Sjkh type = get_partition_type(); 5188702Sjkh if (type == PART_NONE) 5198669Sphk break; 5208669Sphk 5218702Sjkh if (type == PART_FILESYSTEM) { 5228702Sjkh if ((p = get_mountpoint(NULL)) == NULL) 5238702Sjkh break; 5248702Sjkh else if (!strcmp(p->mountpoint, "/")) 5258702Sjkh flags |= CHUNK_IS_ROOT; 5268702Sjkh else 5278702Sjkh flags &= ~CHUNK_IS_ROOT; 5288702Sjkh } else 5298702Sjkh p = NULL; 5308702Sjkh 5318702Sjkh if ((flags & CHUNK_IS_ROOT)) { 5328702Sjkh if (!(label_chunk_info[here].c->flags & CHUNK_BSD_COMPAT)) { 5338702Sjkh msgConfirm("This region cannot be used for your root partition as\nthe FreeBSD boot code cannot deal with a root partition created in\nsuch a location. Please choose another location for your root\npartition and try again!"); 5348702Sjkh break; 5358702Sjkh } 5368705Sjkh if (size < ROOT_MIN_SIZE) 5378705Sjkh msgConfirm("Warning: This is smaller than the recommended size for a\nroot partition. For a variety of reasons, root\npartitions should usually be at least %dMB in size", ROOT_MIN_SIZE / ONE_MEG); 5388672Sjkh } 5398751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 5408702Sjkh label_chunk_info[here].c, 5418702Sjkh size, part, 5428702Sjkh (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 5438702Sjkh flags); 5448702Sjkh if (!tmp) { 5458702Sjkh msgConfirm("Unable to create the partition. Too big?"); 5468672Sjkh break; 5478672Sjkh } 5488702Sjkh if ((flags & CHUNK_IS_ROOT) && (tmp->flags & CHUNK_PAST_1024)) { 5498669Sphk msgConfirm("This region cannot be used for your root partition as it starts\nor extends past the 1024'th cylinder mark and is thus a\npoor location to boot from. Please choose another\nlocation for your root partition and try again!"); 5508751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, tmp); 5518669Sphk break; 5528702Sjkh } 5538702Sjkh if (type != PART_SWAP) { 5548669Sphk /* This is needed to tell the newfs -u about the size */ 5558669Sphk tmp->private = new_part(p->mountpoint,p->newfs,tmp->size); 5568669Sphk safe_free(p); 5578702Sjkh } else { 5588589Sjkh tmp->private = p; 5598702Sjkh } 5608702Sjkh tmp->private_free = safe_free; 5618702Sjkh record_label_chunks(); 5628549Sjkh } 5638549Sjkh break; 5648549Sjkh 5658549Sjkh case 'D': /* delete */ 5668549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 5678549Sjkh msg = MSG_NOT_APPLICABLE; 5688549Sjkh break; 5698549Sjkh } 5708549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 5718705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 5728549Sjkh break; 5738549Sjkh } 5748751Sjkh Delete_Chunk(label_chunk_info[here].c->disk, label_chunk_info[here].c); 5758549Sjkh record_label_chunks(); 5768549Sjkh break; 5778549Sjkh 5788549Sjkh case 'M': /* mount */ 5798549Sjkh switch(label_chunk_info[here].type) { 5808549Sjkh case PART_SLICE: 5818549Sjkh msg = MSG_NOT_APPLICABLE; 5828549Sjkh break; 5838549Sjkh 5848549Sjkh case PART_SWAP: 5858549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 5868549Sjkh break; 5878549Sjkh 5888556Sjkh case PART_FAT: 5898549Sjkh case PART_FILESYSTEM: 5908589Sjkh p = get_mountpoint(label_chunk_info[here].c); 5918549Sjkh if (p) { 5928549Sjkh p->newfs = FALSE; 5938722Sjkh if (label_chunk_info[here].type == PART_FAT 5948722Sjkh && (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr") 5958722Sjkh || !strcmp(p->mountpoint, "/var"))) { 5968722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 5978722Sjkh strcpy(p->mountpoint, "/bogus"); 5988722Sjkh } 5998549Sjkh } 6008810Sjkh record_label_chunks(); 6018549Sjkh break; 6028549Sjkh 6038549Sjkh default: 6048549Sjkh msgFatal("Bogus partition under cursor???"); 6058549Sjkh break; 6068549Sjkh } 6078549Sjkh break; 6088549Sjkh 6098549Sjkh case 'N': /* Set newfs options */ 6108549Sjkh if (label_chunk_info[here].c->private && 6118549Sjkh ((PartInfo *)label_chunk_info[here].c->private)->newfs) 6128549Sjkh getNewfsCmd(label_chunk_info[here].c->private); 6138549Sjkh else 6148549Sjkh msg = MSG_NOT_APPLICABLE; 6158549Sjkh break; 6168549Sjkh 6178549Sjkh case 'T': /* Toggle newfs state */ 6188549Sjkh if (label_chunk_info[here].type == PART_FILESYSTEM && 6198669Sphk label_chunk_info[here].c->private) { 6208669Sphk PartInfo *pi = ((PartInfo *) 6218669Sphk label_chunk_info[here].c->private); 6228669Sphk label_chunk_info[here].c->private = new_part( 6238669Sphk pi->mountpoint, 6248669Sphk !pi->newfs, 6258669Sphk label_chunk_info[here].c->size); 6268669Sphk safe_free(pi); 6278669Sphk } 6288549Sjkh else 6298549Sjkh msg = MSG_NOT_APPLICABLE; 6308549Sjkh break; 6318549Sjkh 6328549Sjkh case 'W': 6338549Sjkh if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\nThis is an entirely undocumented feature which you are not\nexpected to understand!")) { 6348549Sjkh int i; 6358549Sjkh Device **devs; 6368549Sjkh 6378549Sjkh dialog_clear(); 6388549Sjkh end_dialog(); 6398549Sjkh DialogActive = FALSE; 6408549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 6418549Sjkh if (!devs) { 6428549Sjkh msgConfirm("Can't find any disk devicse!"); 6438549Sjkh break; 6448549Sjkh } 6458668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 6468613Sjkh if (devs[i]->enabled) 6478613Sjkh slice_wizard(((Disk *)devs[i]->private)); 6488613Sjkh } 6498665Sphk DialogActive = TRUE; 6508549Sjkh dialog_clear(); 6518549Sjkh record_label_chunks(); 6528549Sjkh } 6538549Sjkh else 6548549Sjkh msg = "A most prudent choice!"; 6558549Sjkh break; 6568549Sjkh 6578549Sjkh case 27: /* ESC */ 6588549Sjkh labeling = FALSE; 6598549Sjkh break; 6608549Sjkh 6618549Sjkh default: 6628549Sjkh beep(); 6638549Sjkh msg = "Type F1 or ? for help"; 6648549Sjkh break; 6658549Sjkh } 6668549Sjkh } 6678549Sjkh variable_set2(DISK_LABELLED, "yes"); 6688581Sjkh dialog_clear(); 6698576Sjkh return 0; 6708549Sjkh} 6718549Sjkh 6728549Sjkh 6738549Sjkh 674