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$ 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> 39127081Sjhb#include <inttypes.h> 40133040Smarcel#include <libdisk.h> 418549Sjkh#include <sys/disklabel.h> 4210882Speter#include <sys/param.h> 4310882Speter#include <sys/sysctl.h> 448549Sjkh 4588996Sdillon#define AUTO_HOME 0 /* do not create /home automatically */ 4688996Sdillon 478549Sjkh/* 488549Sjkh * Everything to do with editing the contents of disk labels. 498549Sjkh */ 508549Sjkh 518549Sjkh/* A nice message we use a lot in the disklabel editor */ 528549Sjkh#define MSG_NOT_APPLICABLE "That option is not applicable here" 538549Sjkh 548549Sjkh/* Where to start printing the freebsd slices */ 558549Sjkh#define CHUNK_SLICE_START_ROW 2 568622Sjkh#define CHUNK_PART_START_ROW 11 578549Sjkh 588549Sjkh/* The smallest filesystem we're willing to create */ 598702Sjkh#define FS_MIN_SIZE ONE_MEG 608549Sjkh 6187557Sdillon/* 6287557Sdillon * Minimum partition sizes 6387557Sdillon */ 64186075Skensmith#if defined(__ia64__) || defined(__sparc64__) || defined(__amd64__) 65209764Sbrucec#define ROOT_MIN_SIZE 280 6644601Sjkh#else 67209764Sbrucec#define ROOT_MIN_SIZE 180 6844601Sjkh#endif 6987557Sdillon#define SWAP_MIN_SIZE 32 70164717Snyan#define USR_MIN_SIZE 160 7187557Sdillon#define VAR_MIN_SIZE 20 7287583Sdillon#define TMP_MIN_SIZE 20 7387557Sdillon#define HOME_MIN_SIZE 20 748549Sjkh 7587557Sdillon/* 7687557Sdillon * Swap size limit for auto-partitioning (4G). 7787557Sdillon */ 7887557Sdillon#define SWAP_AUTO_LIMIT_SIZE 4096 7944601Sjkh 8087557Sdillon/* 8187557Sdillon * Default partition sizes. If we do not have sufficient disk space 8287557Sdillon * for this configuration we scale things relative to the NOM vs DEFAULT 8387557Sdillon * sizes. If the disk is larger then /home will get any remaining space. 8487557Sdillon */ 85209764Sbrucec#define ROOT_DEFAULT_SIZE 1024 86149136Scperciva#define USR_DEFAULT_SIZE 8192 87209764Sbrucec#define VAR_DEFAULT_SIZE 4096 88209764Sbrucec#define TMP_DEFAULT_SIZE 1024 8987557Sdillon#define HOME_DEFAULT_SIZE USR_DEFAULT_SIZE 9012661Speter 9187557Sdillon/* 9287557Sdillon * Nominal partition sizes. These are used to scale the default sizes down 9387557Sdillon * when we have insufficient disk space. If this isn't sufficient we scale 9487557Sdillon * down using the MIN sizes instead. 9587557Sdillon */ 96209764Sbrucec#define ROOT_NOMINAL_SIZE 512 97149136Scperciva#define USR_NOMINAL_SIZE 1536 98209764Sbrucec#define VAR_NOMINAL_SIZE 512 99149136Scperciva#define TMP_NOMINAL_SIZE 128 10087557Sdillon#define HOME_NOMINAL_SIZE USR_NOMINAL_SIZE 10112661Speter 10215440Sjkh/* The bottom-most row we're allowed to scribble on */ 10329249Sjkh#define CHUNK_ROW_MAX 16 10415440Sjkh 10515440Sjkh 1068549Sjkh/* All the chunks currently displayed on the screen */ 1078549Sjkhstatic struct { 1088549Sjkh struct chunk *c; 1098549Sjkh PartType type; 1108549Sjkh} label_chunk_info[MAX_CHUNKS + 1]; 1118549Sjkhstatic int here; 1128549Sjkh 11329249Sjkh/*** with this value we try to track the most recently added label ***/ 11429249Sjkhstatic int label_focus = 0, pslice_focus = 0; 11529249Sjkh 11630345Sjkhstatic int diskLabel(Device *dev); 11730345Sjkhstatic int diskLabelNonInteractive(Device *dev); 11887557Sdillonstatic char *try_auto_label(Device **devs, Device *dev, int perc, int *req); 11912661Speter 12030345Sjkhstatic int 12130345SjkhlabelHook(dialogMenuItem *selected) 12230345Sjkh{ 12330345Sjkh Device **devs = NULL; 12430345Sjkh 12530345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 12630345Sjkh if (!devs) { 12730345Sjkh msgConfirm("Unable to find disk %s!", selected->prompt); 12830345Sjkh return DITEM_FAILURE; 12930345Sjkh } 13030345Sjkh /* Toggle enabled status? */ 13130345Sjkh if (!devs[0]->enabled) { 13230345Sjkh devs[0]->enabled = TRUE; 13330345Sjkh diskLabel(devs[0]); 13430345Sjkh } 13530345Sjkh else 13630345Sjkh devs[0]->enabled = FALSE; 13754587Sjkh return DITEM_SUCCESS; 13830345Sjkh} 13930345Sjkh 14030345Sjkhstatic int 14130345SjkhlabelCheck(dialogMenuItem *selected) 14230345Sjkh{ 14330345Sjkh Device **devs = NULL; 14430345Sjkh 14530345Sjkh devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 14630345Sjkh if (!devs || devs[0]->enabled == FALSE) 14730345Sjkh return FALSE; 14830345Sjkh return TRUE; 14930345Sjkh} 15030345Sjkh 15112661Speterint 15215091SjkhdiskLabelEditor(dialogMenuItem *self) 15312661Speter{ 15430345Sjkh DMenu *menu; 15512661Speter Device **devs; 15630345Sjkh int i, cnt; 15712661Speter 15830345Sjkh i = 0; 15930345Sjkh cnt = diskGetSelectCount(&devs); 16030345Sjkh if (cnt == -1) { 16112661Speter msgConfirm("No disks found! Please verify that your disk controller is being\n" 16212661Speter "properly probed at boot time. See the Hardware Guide on the\n" 16312661Speter "Documentation menu for clues on diagnosing this type of problem."); 16415242Sjkh return DITEM_FAILURE; 16512661Speter } 16630345Sjkh else if (cnt) { 16730345Sjkh /* Some are already selected */ 16897667Sjhb if (variable_get(VAR_NONINTERACTIVE) && 16997667Sjhb !variable_get(VAR_DISKINTERACTIVE)) 17034543Sjkh i = diskLabelNonInteractive(NULL); 17130381Sjkh else 17234543Sjkh i = diskLabel(NULL); 17312661Speter } 17430345Sjkh else { 17530345Sjkh /* No disks are selected, fall-back case now */ 17630345Sjkh cnt = deviceCount(devs); 17730345Sjkh if (cnt == 1) { 17830345Sjkh devs[0]->enabled = TRUE; 17997667Sjhb if (variable_get(VAR_NONINTERACTIVE) && 18097667Sjhb !variable_get(VAR_DISKINTERACTIVE)) 18130345Sjkh i = diskLabelNonInteractive(devs[0]); 18230345Sjkh else 18330345Sjkh i = diskLabel(devs[0]); 18430345Sjkh } 18530345Sjkh else { 18630345Sjkh menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck); 18730345Sjkh if (!menu) { 18830345Sjkh msgConfirm("No devices suitable for installation found!\n\n" 18930345Sjkh "Please verify that your disk controller (and attached drives)\n" 19030345Sjkh "were detected properly. This can be done by pressing the\n" 19130345Sjkh "[Scroll Lock] key and using the Arrow keys to move back to\n" 19230345Sjkh "the boot messages. Press [Scroll Lock] again to return."); 19330345Sjkh i = DITEM_FAILURE; 19430345Sjkh } 19530345Sjkh else { 19630345Sjkh i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 19730345Sjkh free(menu); 19830345Sjkh } 19930345Sjkh } 20012661Speter } 20118744Sjkh if (DITEM_STATUS(i) != DITEM_FAILURE) { 20274156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 20343685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 20418744Sjkh } 20512661Speter return i; 20612661Speter} 20712661Speter 20812661Speterint 20915091SjkhdiskLabelCommit(dialogMenuItem *self) 21012661Speter{ 21112661Speter char *cp; 21212661Speter int i; 21312661Speter 21412661Speter /* Already done? */ 21517025Sjkh if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes")) 21615242Sjkh i = DITEM_SUCCESS; 21712661Speter else if (!cp) { 21812661Speter msgConfirm("You must assign disk labels before this option can be used."); 21915242Sjkh i = DITEM_FAILURE; 22012661Speter } 22112661Speter /* The routine will guard against redundant writes, just as this one does */ 22215419Sjkh else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS) 22315242Sjkh i = DITEM_FAILURE; 22415419Sjkh else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS) 22515242Sjkh i = DITEM_FAILURE; 22612661Speter else { 22712661Speter msgInfo("All filesystem information written successfully."); 22843685Sjkh variable_set2(DISK_LABELLED, "written", 0); 22915242Sjkh i = DITEM_SUCCESS; 23012661Speter } 23112661Speter return i; 23212661Speter} 23312661Speter 2348549Sjkh/* See if we're already using a desired partition name */ 2358549Sjkhstatic Boolean 2368549Sjkhcheck_conflict(char *name) 2378549Sjkh{ 2388549Sjkh int i; 2398549Sjkh 2408751Sjkh for (i = 0; label_chunk_info[i].c; i++) 241121890Smarcel if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT 242121890Smarcel || label_chunk_info[i].type == PART_EFI) && label_chunk_info[i].c->private_data 24314793Sjoerg && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name)) 2448549Sjkh return TRUE; 2458549Sjkh return FALSE; 2468549Sjkh} 2478549Sjkh 2488549Sjkh/* How much space is in this FreeBSD slice? */ 249127081Sjhbstatic daddr_t 2508549Sjkhspace_free(struct chunk *c) 2518549Sjkh{ 25212661Speter struct chunk *c1; 253127081Sjhb daddr_t sz = c->size; 2548549Sjkh 25512661Speter for (c1 = c->part; c1; c1 = c1->next) { 2568549Sjkh if (c1->type != unused) 2578549Sjkh sz -= c1->size; 2588549Sjkh } 2598549Sjkh if (sz < 0) 2608549Sjkh msgFatal("Partitions are larger than actual chunk??"); 2618549Sjkh return sz; 2628549Sjkh} 2638549Sjkh 2648549Sjkh/* Snapshot the current situation into the displayed chunks structure */ 2658549Sjkhstatic void 26630345Sjkhrecord_label_chunks(Device **devs, Device *dev) 2678549Sjkh{ 2688549Sjkh int i, j, p; 2698549Sjkh struct chunk *c1, *c2; 2708556Sjkh Disk *d; 2718549Sjkh 2728549Sjkh j = p = 0; 2738556Sjkh /* First buzz through and pick up the FreeBSD slices */ 2748549Sjkh for (i = 0; devs[i]; i++) { 27530345Sjkh if ((dev && devs[i] != dev) || !devs[i]->enabled) 2768556Sjkh continue; 2778556Sjkh d = (Disk *)devs[i]->private; 2788556Sjkh if (!d->chunks) 2798556Sjkh msgFatal("No chunk list found for %s!", d->name); 2808549Sjkh 281121890Smarcel#ifdef __ia64__ 282121890Smarcel label_chunk_info[j].type = PART_SLICE; 283121890Smarcel label_chunk_info[j].c = d->chunks; 284121890Smarcel j++; 285121890Smarcel#endif 286121890Smarcel 2878556Sjkh /* Put the slice entries first */ 2888556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 2898549Sjkh if (c1->type == freebsd) { 2908549Sjkh label_chunk_info[j].type = PART_SLICE; 2918549Sjkh label_chunk_info[j].c = c1; 2928549Sjkh ++j; 2938549Sjkh } 294129259Sgrehan#ifdef __powerpc__ 295129259Sgrehan if (c1->type == apple) { 296129259Sgrehan label_chunk_info[j].type = PART_SLICE; 297129259Sgrehan label_chunk_info[j].c = c1; 298129259Sgrehan ++j; 299129259Sgrehan } 300129259Sgrehan#endif 3018549Sjkh } 3028549Sjkh } 30312661Speter 3048556Sjkh /* Now run through again and get the FreeBSD partition entries */ 3058556Sjkh for (i = 0; devs[i]; i++) { 3068556Sjkh if (!devs[i]->enabled) 3078556Sjkh continue; 3088556Sjkh d = (Disk *)devs[i]->private; 3098549Sjkh /* Then buzz through and pick up the partitions */ 3108556Sjkh for (c1 = d->chunks->part; c1; c1 = c1->next) { 3118549Sjkh if (c1->type == freebsd) { 3128549Sjkh for (c2 = c1->part; c2; c2 = c2->next) { 3138549Sjkh if (c2->type == part) { 3148549Sjkh if (c2->subtype == FS_SWAP) 3158549Sjkh label_chunk_info[j].type = PART_SWAP; 3168549Sjkh else 3178549Sjkh label_chunk_info[j].type = PART_FILESYSTEM; 3188549Sjkh label_chunk_info[j].c = c2; 3198549Sjkh ++j; 3208549Sjkh } 3218549Sjkh } 3228549Sjkh } 323121890Smarcel else if (c1->type == fat) { 3248549Sjkh label_chunk_info[j].type = PART_FAT; 3258549Sjkh label_chunk_info[j].c = c1; 3268702Sjkh ++j; 3278549Sjkh } 328121864Smarcel#ifdef __ia64__ 329121890Smarcel else if (c1->type == efi) { 330121890Smarcel label_chunk_info[j].type = PART_EFI; 331121890Smarcel label_chunk_info[j].c = c1; 332121890Smarcel ++j; 333121890Smarcel } 334121864Smarcel else if (c1->type == part) { 335121864Smarcel if (c1->subtype == FS_SWAP) 336121864Smarcel label_chunk_info[j].type = PART_SWAP; 337121864Smarcel else 338121864Smarcel label_chunk_info[j].type = PART_FILESYSTEM; 339121864Smarcel label_chunk_info[j].c = c1; 340121864Smarcel ++j; 341121864Smarcel } 342121864Smarcel#endif 343129259Sgrehan#ifdef __powerpc__ 344129259Sgrehan else if (c1->type == apple) { 345129259Sgrehan for (c2 = c1->part; c2; c2 = c2->next) { 346129259Sgrehan if (c2->type == part) { 347129259Sgrehan if (c2->subtype == FS_SWAP) 348129259Sgrehan label_chunk_info[j].type = PART_SWAP; 349129259Sgrehan else 350129259Sgrehan label_chunk_info[j].type = PART_FILESYSTEM; 351129259Sgrehan label_chunk_info[j].c = c2; 352129259Sgrehan ++j; 353129259Sgrehan } 354129259Sgrehan } 355129259Sgrehan } 356129259Sgrehan#endif 3578549Sjkh } 3588549Sjkh } 3598549Sjkh label_chunk_info[j].c = NULL; 36029249Sjkh if (here >= j) { 3618549Sjkh here = j ? j - 1 : 0; 36229249Sjkh } 3638549Sjkh} 3648549Sjkh 3658549Sjkh/* A new partition entry */ 3668549Sjkhstatic PartInfo * 367133106Smarcelnew_part(PartType type, char *mpoint, Boolean newfs) 3688549Sjkh{ 369107565Srwatson PartInfo *pi; 3708549Sjkh 3719202Srgrimes if (!mpoint) 372133106Smarcel mpoint = (type == PART_EFI) ? "/efi" : "/change_me"; 3739202Srgrimes 374107565Srwatson pi = (PartInfo *)safe_malloc(sizeof(PartInfo)); 375107565Srwatson sstrncpy(pi->mountpoint, mpoint, FILENAME_MAX); 376107565Srwatson 377107565Srwatson pi->do_newfs = newfs; 378107565Srwatson 379133106Smarcel if (type == PART_EFI) { 380133106Smarcel pi->newfs_type = NEWFS_MSDOS; 381133106Smarcel } else { 382133106Smarcel pi->newfs_type = NEWFS_UFS; 383133106Smarcel strcpy(pi->newfs_data.newfs_ufs.user_options, ""); 384133106Smarcel pi->newfs_data.newfs_ufs.acls = FALSE; 385133106Smarcel pi->newfs_data.newfs_ufs.multilabel = FALSE; 386133106Smarcel pi->newfs_data.newfs_ufs.softupdates = strcmp(mpoint, "/"); 387133106Smarcel pi->newfs_data.newfs_ufs.ufs1 = FALSE; 388133106Smarcel } 389107565Srwatson 390107565Srwatson return pi; 3918549Sjkh} 3928549Sjkh 3938549Sjkh/* Get the mountpoint for a partition and save it away */ 39412661Speterstatic PartInfo * 395133106Smarcelget_mountpoint(PartType type, struct chunk *old) 3968549Sjkh{ 3978549Sjkh char *val; 3988549Sjkh PartInfo *tmp; 399106822Sjhb Boolean newfs; 4008549Sjkh 40114793Sjoerg if (old && old->private_data) 40214793Sjoerg tmp = old->private_data; 4038810Sjkh else 4048810Sjkh tmp = NULL; 405133106Smarcel val = (tmp != NULL) ? tmp->mountpoint : (type == PART_EFI) ? "/efi" : NULL; 406133106Smarcel val = msgGetInput(val, "Please specify a mount point for the partition"); 4078764Sjkh if (!val || !*val) { 4088751Sjkh if (!old) 4098751Sjkh return NULL; 4108751Sjkh else { 41114793Sjoerg free(old->private_data); 41214793Sjoerg old->private_data = NULL; 4138751Sjkh } 4148669Sphk return NULL; 4158751Sjkh } 4168669Sphk 4178669Sphk /* Is it just the same value? */ 4188810Sjkh if (tmp && !strcmp(tmp->mountpoint, val)) 4198669Sphk return NULL; 4208810Sjkh 4218810Sjkh /* Did we use it already? */ 4228669Sphk if (check_conflict(val)) { 4238669Sphk msgConfirm("You already have a mount point for %s assigned!", val); 4248669Sphk return NULL; 4258549Sjkh } 4268810Sjkh 4278810Sjkh /* Is it bogus? */ 4288669Sphk if (*val != '/') { 4298669Sphk msgConfirm("Mount point must start with a / character"); 4308669Sphk return NULL; 4318669Sphk } 4328810Sjkh 4338810Sjkh /* Is it going to be mounted on root? */ 4348669Sphk if (!strcmp(val, "/")) { 4358669Sphk if (old) 4368669Sphk old->flags |= CHUNK_IS_ROOT; 4378810Sjkh } 4388810Sjkh else if (old) 4398669Sphk old->flags &= ~CHUNK_IS_ROOT; 4408810Sjkh 441106823Sjhb newfs = TRUE; 442106822Sjhb if (tmp) { 443107565Srwatson newfs = tmp->do_newfs; 444106822Sjhb safe_free(tmp); 445106822Sjhb } 44646615Sjkh val = string_skipwhite(string_prune(val)); 447133106Smarcel tmp = new_part(type, val, newfs); 4488669Sphk if (old) { 44914793Sjoerg old->private_data = tmp; 4508669Sphk old->private_free = safe_free; 4518669Sphk } 4528669Sphk return tmp; 4538549Sjkh} 4548549Sjkh 4558549Sjkh/* Get the type of the new partiton */ 4568549Sjkhstatic PartType 4578549Sjkhget_partition_type(void) 4588549Sjkh{ 4598549Sjkh char selection[20]; 4608669Sphk int i; 4618549Sjkh static unsigned char *fs_types[] = { 462121890Smarcel#ifdef __ia64__ 463121890Smarcel "EFI", "An EFI system partition", 464121890Smarcel#endif 465121890Smarcel "FS", "A file system", 466121890Smarcel "Swap", "A swap partition.", 4678549Sjkh }; 46854587Sjkh WINDOW *w = savescr(); 46954587Sjkh 4708669Sphk i = dialog_menu("Please choose a partition type", 471121890Smarcel "If you want to use this partition for swap space, select Swap.\n" 472121890Smarcel "If you want to put a filesystem on it, choose FS.", 473121890Smarcel -1, -1, 474121890Smarcel#ifdef __ia64__ 475121890Smarcel 3, 3, 476121890Smarcel#else 477121890Smarcel 2, 2, 478121890Smarcel#endif 479121890Smarcel fs_types, selection, NULL, NULL); 48054587Sjkh restorescr(w); 4818669Sphk if (!i) { 482121890Smarcel#ifdef __ia64__ 483121890Smarcel if (!strcmp(selection, "EFI")) 484121890Smarcel return PART_EFI; 485121890Smarcel#endif 4868549Sjkh if (!strcmp(selection, "FS")) 4878549Sjkh return PART_FILESYSTEM; 4888549Sjkh else if (!strcmp(selection, "Swap")) 4898549Sjkh return PART_SWAP; 4908549Sjkh } 4918549Sjkh return PART_NONE; 4928549Sjkh} 4938549Sjkh 4948549Sjkh/* If the user wants a special newfs command for this, set it */ 4958549Sjkhstatic void 4968549SjkhgetNewfsCmd(PartInfo *p) 4978549Sjkh{ 498107565Srwatson char buffer[NEWFS_CMD_ARGS_MAX]; 4998549Sjkh char *val; 5008549Sjkh 501107565Srwatson switch (p->newfs_type) { 502107565Srwatson case NEWFS_UFS: 503107565Srwatson snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s %s %s %s", 504107565Srwatson NEWFS_UFS_CMD, p->newfs_data.newfs_ufs.softupdates ? "-U" : "", 505113751Srwatson p->newfs_data.newfs_ufs.ufs1 ? "-O1" : "-O2", 506107565Srwatson p->newfs_data.newfs_ufs.user_options); 507107565Srwatson break; 508107565Srwatson case NEWFS_MSDOS: 509107565Srwatson snprintf(buffer, NEWFS_CMD_ARGS_MAX, "%s", NEWFS_MSDOS_CMD); 510107565Srwatson break; 511107565Srwatson case NEWFS_CUSTOM: 512107565Srwatson strcpy(buffer, p->newfs_data.newfs_custom.command); 513107565Srwatson break; 514107565Srwatson } 515107565Srwatson 516107565Srwatson val = msgGetInput(buffer, 517107565Srwatson "Please enter the newfs command and options you'd like to use in\n" 518107565Srwatson "creating this file system."); 519107565Srwatson if (val != NULL) { 520107565Srwatson p->newfs_type = NEWFS_CUSTOM; 521107565Srwatson strlcpy(p->newfs_data.newfs_custom.command, val, NEWFS_CMD_ARGS_MAX); 522107565Srwatson } 5238549Sjkh} 5248549Sjkh 525107565Srwatsonstatic void 526107565SrwatsongetNewfsOptionalArguments(PartInfo *p) 527107565Srwatson{ 528107565Srwatson char buffer[NEWFS_CMD_ARGS_MAX]; 529107565Srwatson char *val; 530107565Srwatson 531107565Srwatson /* Must be UFS, per argument checking in I/O routines. */ 532107565Srwatson 533107565Srwatson strlcpy(buffer, p->newfs_data.newfs_ufs.user_options, 534107565Srwatson NEWFS_CMD_ARGS_MAX); 535107565Srwatson val = msgGetInput(buffer, 536107565Srwatson "Please enter any additional UFS newfs options you'd like to\n" 537107565Srwatson "use in creating this file system."); 538107565Srwatson if (val != NULL) 539107565Srwatson strlcpy(p->newfs_data.newfs_ufs.user_options, val, 540107565Srwatson NEWFS_CMD_ARGS_MAX); 541107565Srwatson} 542107565Srwatson 54376299Sjkh#define MAX_MOUNT_NAME 9 5448549Sjkh 5458549Sjkh#define PART_PART_COL 0 54654014Sjkh#define PART_MOUNT_COL 10 5478549Sjkh#define PART_SIZE_COL (PART_MOUNT_COL + MAX_MOUNT_NAME + 3) 54849202Sbrian#define PART_NEWFS_COL (PART_SIZE_COL + 8) 54976299Sjkh#define PART_OFF 38 5508549Sjkh 55129249Sjkh#define TOTAL_AVAIL_LINES (10) 55229249Sjkh#define PSLICE_SHOWABLE (4) 55329249Sjkh 55429249Sjkh 5558549Sjkh/* stick this all up on the screen */ 5568549Sjkhstatic void 5578549Sjkhprint_label_chunks(void) 5588549Sjkh{ 559127081Sjhb int i, j, srow, prow, pcol; 560127081Sjhb daddr_t sz; 56129249Sjkh char clrmsg[80]; 56229633Sjkh int ChunkPartStartRow; 56329633Sjkh WINDOW *ChunkWin; 5648549Sjkh 56529249Sjkh /********************************************************/ 56629249Sjkh /*** These values are for controling screen resources ***/ 56729249Sjkh /*** Each label line holds up to 2 labels, so beware! ***/ 56829249Sjkh /*** strategy will be to try to always make sure the ***/ 56929249Sjkh /*** highlighted label is in the active display area. ***/ 57029249Sjkh /********************************************************/ 57129249Sjkh int pslice_max, label_max; 57229249Sjkh int pslice_count, label_count, label_focus_found, pslice_focus_found; 57329249Sjkh 5748549Sjkh attrset(A_REVERSE); 5758549Sjkh mvaddstr(0, 25, "FreeBSD Disklabel Editor"); 5768549Sjkh attrset(A_NORMAL); 5778549Sjkh 57829633Sjkh /*** Count the number of parition slices ***/ 57929633Sjkh pslice_count = 0; 58029633Sjkh for (i = 0; label_chunk_info[i].c ; i++) { 58129633Sjkh if (label_chunk_info[i].type == PART_SLICE) 58229633Sjkh ++pslice_count; 58329633Sjkh } 58429633Sjkh pslice_max = pslice_count; 585121864Smarcel 58629633Sjkh /*** 4 line max for partition slices ***/ 58729633Sjkh if (pslice_max > PSLICE_SHOWABLE) { 58829633Sjkh pslice_max = PSLICE_SHOWABLE; 58929633Sjkh } 59029633Sjkh ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max; 59129633Sjkh 59229633Sjkh /*** View partition slices modulo pslice_max ***/ 59329633Sjkh label_max = TOTAL_AVAIL_LINES - pslice_max; 59429633Sjkh 5958549Sjkh for (i = 0; i < 2; i++) { 59615440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part"); 59715440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----"); 5988549Sjkh 59915440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount"); 60015440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----"); 6018549Sjkh 60249202Sbrian mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size"); 60349202Sbrian mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----"); 6048549Sjkh 60515440Sjkh mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs"); 60615440Sjkh mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----"); 6078549Sjkh } 6088549Sjkh srow = CHUNK_SLICE_START_ROW; 60915440Sjkh prow = 0; 6108549Sjkh pcol = 0; 6118549Sjkh 61229249Sjkh /*** these variables indicate that the focused item is shown currently ***/ 61329249Sjkh label_focus_found = 0; 61429249Sjkh pslice_focus_found = 0; 61529249Sjkh 61629249Sjkh label_count = 0; 61729249Sjkh pslice_count = 0; 61829249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, " "); 61929249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, " "); 62029249Sjkh 62129633Sjkh ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0); 62229633Sjkh 62329633Sjkh wclear(ChunkWin); 62429633Sjkh /*** wrefresh(ChunkWin); ***/ 62529633Sjkh 6268751Sjkh for (i = 0; label_chunk_info[i].c; i++) { 6278549Sjkh /* Is it a slice entry displayed at the top? */ 6288549Sjkh if (label_chunk_info[i].type == PART_SLICE) { 62929249Sjkh /*** This causes the new pslice to replace the previous display ***/ 63029249Sjkh /*** focus must remain on the most recently active pslice ***/ 63129249Sjkh if (pslice_count == pslice_max) { 63229249Sjkh if (pslice_focus_found) { 63329249Sjkh /*** This is where we can mark the more following ***/ 63429249Sjkh attrset(A_BOLD); 63529249Sjkh mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***"); 63629249Sjkh attrset(A_NORMAL); 63729249Sjkh continue; 63829249Sjkh } 63929249Sjkh else { 64029249Sjkh /*** this is where we set the more previous ***/ 64129249Sjkh attrset(A_BOLD); 64229249Sjkh mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***"); 64329249Sjkh attrset(A_NORMAL); 64429249Sjkh pslice_count = 0; 64529249Sjkh srow = CHUNK_SLICE_START_ROW; 64629249Sjkh } 64729249Sjkh } 64829249Sjkh 6498549Sjkh sz = space_free(label_chunk_info[i].c); 65015440Sjkh if (i == here) 65116208Sjkh attrset(ATTR_SELECTED); 65229249Sjkh if (i == pslice_focus) 65329249Sjkh pslice_focus_found = -1; 65429249Sjkh 655121864Smarcel if (label_chunk_info[i].c->type == whole) { 656121864Smarcel if (sz >= 100 * ONE_GIG) 657121864Smarcel mvprintw(srow++, 0, 658127081Sjhb "Disk: %s\t\tFree: %jd blocks (%jdGB)", 659127081Sjhb label_chunk_info[i].c->disk->name, (intmax_t)sz, 660127081Sjhb (intmax_t)(sz / ONE_GIG)); 661121864Smarcel else 662121864Smarcel mvprintw(srow++, 0, 663127081Sjhb "Disk: %s\t\tFree: %jd blocks (%jdMB)", 664127081Sjhb label_chunk_info[i].c->disk->name, (intmax_t)sz, 665127081Sjhb (intmax_t)(sz / ONE_MEG)); 666121864Smarcel } else { 667121864Smarcel if (sz >= 100 * ONE_GIG) 668107751Sphk mvprintw(srow++, 0, 669127081Sjhb "Disk: %s\tPartition name: %s\tFree: %jd blocks (%jdGB)", 670107751Sphk label_chunk_info[i].c->disk->name, 671107751Sphk label_chunk_info[i].c->name, 672127081Sjhb (intmax_t)sz, (intmax_t)(sz / ONE_GIG)); 673121864Smarcel else 674107751Sphk mvprintw(srow++, 0, 675127081Sjhb "Disk: %s\tPartition name: %s\tFree: %jd blocks (%jdMB)", 676107751Sphk label_chunk_info[i].c->disk->name, 677107751Sphk label_chunk_info[i].c->name, 678127081Sjhb (intmax_t)sz, (intmax_t)(sz / ONE_MEG)); 679121864Smarcel } 68015440Sjkh attrset(A_NORMAL); 68115440Sjkh clrtoeol(); 68215440Sjkh move(0, 0); 68329633Sjkh /*** refresh(); ***/ 68429249Sjkh ++pslice_count; 6858549Sjkh } 68615440Sjkh /* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */ 6878549Sjkh else { 688107565Srwatson char onestr[PART_OFF], num[10], *mountpoint, newfs[12]; 6898549Sjkh 6908549Sjkh /* 6918549Sjkh * We copy this into a blank-padded string so that it looks like 6928549Sjkh * a solid bar in reverse-video 6938549Sjkh */ 6948549Sjkh memset(onestr, ' ', PART_OFF - 1); 6958549Sjkh onestr[PART_OFF - 1] = '\0'; 69629249Sjkh 69729249Sjkh /*** Track how many labels have been displayed ***/ 69829249Sjkh if (label_count == ((label_max - 1 ) * 2)) { 69929249Sjkh if (label_focus_found) { 70029249Sjkh continue; 70129249Sjkh } 70229249Sjkh else { 70329249Sjkh label_count = 0; 70429249Sjkh prow = 0; 70529249Sjkh pcol = 0; 70629249Sjkh } 70729249Sjkh } 70829249Sjkh 70915440Sjkh /* Go for two columns if we've written one full columns worth */ 71029249Sjkh /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/ 71129249Sjkh if (label_count == label_max - 1) { 7128549Sjkh pcol = PART_OFF; 71315440Sjkh prow = 0; 7148549Sjkh } 7158705Sjkh memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name)); 7168549Sjkh /* If it's a filesystem, display the mountpoint */ 717121890Smarcel if (label_chunk_info[i].c->private_data && (label_chunk_info[i].type == PART_FILESYSTEM 718121890Smarcel || label_chunk_info[i].type == PART_FAT || label_chunk_info[i].type == PART_EFI)) 719121890Smarcel mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint; 72023529Sjkh else if (label_chunk_info[i].type == PART_SWAP) 72123529Sjkh mountpoint = "swap"; 72210882Speter else 72310882Speter mountpoint = "<none>"; 72410882Speter 72510882Speter /* Now display the newfs field */ 726121890Smarcel if (label_chunk_info[i].type == PART_FAT) 727106885Smarcel strcpy(newfs, "DOS"); 728106885Smarcel#if defined(__ia64__) 729121890Smarcel else if (label_chunk_info[i].type == PART_EFI) { 730121890Smarcel strcpy(newfs, "EFI"); 731121890Smarcel if (label_chunk_info[i].c->private_data) { 732121890Smarcel strcat(newfs, " "); 733121890Smarcel PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data; 734121890Smarcel strcat(newfs, pi->do_newfs ? " Y" : " N"); 735106885Smarcel } 736121890Smarcel } 737106885Smarcel#endif 73874086Sjkh else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) { 739107565Srwatson PartInfo *pi = (PartInfo *)label_chunk_info[i].c->private_data; 740107565Srwatson 741107565Srwatson switch (pi->newfs_type) { 742107565Srwatson case NEWFS_UFS: 743107565Srwatson strcpy(newfs, NEWFS_UFS_STRING); 744113751Srwatson if (pi->newfs_data.newfs_ufs.ufs1) 745113751Srwatson strcat(newfs, "1"); 746113751Srwatson else 747107565Srwatson strcat(newfs, "2"); 748107565Srwatson if (pi->newfs_data.newfs_ufs.softupdates) 749107565Srwatson strcat(newfs, "+S"); 750107565Srwatson else 751107565Srwatson strcat(newfs, " "); 752107565Srwatson 753107565Srwatson break; 754107565Srwatson case NEWFS_MSDOS: 755107565Srwatson strcpy(newfs, "FAT"); 756107565Srwatson break; 757107565Srwatson case NEWFS_CUSTOM: 758107565Srwatson strcpy(newfs, "CUST"); 759107565Srwatson break; 760107565Srwatson } 761107565Srwatson strcat(newfs, pi->do_newfs ? " Y" : " N "); 76274086Sjkh } 76310882Speter else if (label_chunk_info[i].type == PART_SWAP) 76474086Sjkh strcpy(newfs, "SWAP"); 76510882Speter else 76674086Sjkh strcpy(newfs, "*"); 7678549Sjkh for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++) 7688549Sjkh onestr[PART_MOUNT_COL + j] = mountpoint[j]; 769107751Sphk if (label_chunk_info[i].c->size == 0) 770127081Sjhb snprintf(num, 10, "%5dMB", 0); 771107751Sphk else if (label_chunk_info[i].c->size < (100 * ONE_GIG)) 772127081Sjhb snprintf(num, 10, "%5jdMB", 773127081Sjhb (intmax_t)label_chunk_info[i].c->size / ONE_MEG); 774107751Sphk else 775127081Sjhb snprintf(num, 10, "%5jdGB", 776127081Sjhb (intmax_t)label_chunk_info[i].c->size / ONE_GIG); 7778549Sjkh memcpy(onestr + PART_SIZE_COL, num, strlen(num)); 7788549Sjkh memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs)); 7798549Sjkh onestr[PART_NEWFS_COL + strlen(newfs)] = '\0'; 78029633Sjkh if (i == label_focus) { 78129633Sjkh label_focus_found = -1; 78229633Sjkh wattrset(ChunkWin, A_BOLD); 78329633Sjkh } 78415440Sjkh if (i == here) 78516208Sjkh wattrset(ChunkWin, ATTR_SELECTED); 78629249Sjkh 78774086Sjkh /*** lazy man's way of expensively padding this string ***/ 78874086Sjkh while (strlen(onestr) < 37) 78929249Sjkh strcat(onestr, " "); 79029249Sjkh 79115440Sjkh mvwaddstr(ChunkWin, prow, pcol, onestr); 79215440Sjkh wattrset(ChunkWin, A_NORMAL); 79315440Sjkh move(0, 0); 7948549Sjkh ++prow; 79529249Sjkh ++label_count; 7968549Sjkh } 7978549Sjkh } 79829249Sjkh 79929249Sjkh /*** this will erase all the extra stuff ***/ 80029249Sjkh memset(clrmsg, ' ', 37); 80129249Sjkh clrmsg[37] = '\0'; 80229249Sjkh 80329249Sjkh while (pslice_count < pslice_max) { 80429249Sjkh mvprintw(srow++, 0, clrmsg); 80529249Sjkh clrtoeol(); 80629249Sjkh ++pslice_count; 80729249Sjkh } 80829633Sjkh while (label_count < (2 * (label_max - 1))) { 80929633Sjkh mvwaddstr(ChunkWin, prow++, pcol, clrmsg); 81029633Sjkh ++label_count; 81129633Sjkh if (prow == (label_max - 1)) { 81229633Sjkh prow = 0; 81329633Sjkh pcol = PART_OFF; 81429633Sjkh } 81529249Sjkh } 81629633Sjkh refresh(); 81729633Sjkh wrefresh(ChunkWin); 8188549Sjkh} 8198549Sjkh 8208549Sjkhstatic void 82118619Sjkhprint_command_summary(void) 8228549Sjkh{ 8238820Sjkh mvprintw(17, 0, "The following commands are valid here (upper or lower case):"); 82474086Sjkh mvprintw(18, 0, "C = Create D = Delete M = Mount pt."); 82515440Sjkh if (!RunningAsInit) 826107565Srwatson mvprintw(18, 56, "W = Write"); 827107565Srwatson mvprintw(19, 0, "N = Newfs Opts Q = Finish S = Toggle SoftUpdates Z = Custom Newfs"); 828107565Srwatson mvprintw(20, 0, "T = Toggle Newfs U = Undo A = Auto Defaults R = Delete+Merge"); 82915695Sjkh mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select."); 8308549Sjkh move(0, 0); 8318549Sjkh} 8328549Sjkh 83318619Sjkhstatic void 83418619Sjkhclear_wins(void) 83518619Sjkh{ 83618619Sjkh clear(); 83729633Sjkh print_label_chunks(); 83818619Sjkh} 83918619Sjkh 84012661Speterstatic int 84130345SjkhdiskLabel(Device *dev) 8428549Sjkh{ 843127081Sjhb daddr_t sz; 844127081Sjhb int key = 0; 8458549Sjkh Boolean labeling; 8468549Sjkh char *msg = NULL; 8479202Srgrimes PartInfo *p, *oldp; 8488549Sjkh PartType type; 8498824Sjkh Device **devs; 85054587Sjkh WINDOW *w = savescr(); 8518549Sjkh 85229628Sjkh label_focus = 0; 85329628Sjkh pslice_focus = 0; 85429633Sjkh here = 0; 85530345Sjkh 85612661Speter devs = deviceFind(NULL, DEVICE_TYPE_DISK); 85712661Speter if (!devs) { 85812661Speter msgConfirm("No disks found!"); 85954587Sjkh restorescr(w); 86015242Sjkh return DITEM_FAILURE; 86112661Speter } 8628549Sjkh labeling = TRUE; 8638549Sjkh keypad(stdscr, TRUE); 86430345Sjkh record_label_chunks(devs, dev); 8658549Sjkh 86618619Sjkh clear(); 8678549Sjkh while (labeling) { 86818744Sjkh char *cp; 86988996Sdillon int rflags = DELCHUNK_NORMAL; 87018744Sjkh 8718549Sjkh print_label_chunks(); 87218619Sjkh print_command_summary(); 8738549Sjkh if (msg) { 87415695Sjkh attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 87512661Speter clrtoeol(); 8768549Sjkh beep(); 8778549Sjkh msg = NULL; 8788549Sjkh } 87915442Sjkh else { 88015442Sjkh move(23, 0); 88115442Sjkh clrtoeol(); 88215442Sjkh } 88318744Sjkh 88418619Sjkh refresh(); 88517397Sjkh key = getch(); 88617397Sjkh switch (toupper(key)) { 88715440Sjkh int i; 88817362Sjkh static char _msg[40]; 8898549Sjkh 8908751Sjkh case '\014': /* ^L */ 89118619Sjkh clear_wins(); 89218619Sjkh break; 8938751Sjkh 89421698Sjkh case '\020': /* ^P */ 8958549Sjkh case KEY_UP: 8968549Sjkh case '-': 8978549Sjkh if (here != 0) 8988549Sjkh --here; 8998751Sjkh else 9008751Sjkh while (label_chunk_info[here + 1].c) 9018751Sjkh ++here; 9028549Sjkh break; 9038549Sjkh 90421698Sjkh case '\016': /* ^N */ 9058549Sjkh case KEY_DOWN: 9068549Sjkh case '+': 9078549Sjkh case '\r': 9088549Sjkh case '\n': 9098751Sjkh if (label_chunk_info[here + 1].c) 9108549Sjkh ++here; 9118751Sjkh else 9128751Sjkh here = 0; 9138549Sjkh break; 9148549Sjkh 9158549Sjkh case KEY_HOME: 9168549Sjkh here = 0; 9178549Sjkh break; 9188549Sjkh 9198549Sjkh case KEY_END: 9208751Sjkh while (label_chunk_info[here + 1].c) 9218549Sjkh ++here; 9228549Sjkh break; 9238549Sjkh 9248549Sjkh case KEY_F(1): 9258549Sjkh case '?': 92612661Speter systemDisplayHelp("partition"); 92718619Sjkh clear_wins(); 9288549Sjkh break; 9298549Sjkh 930113751Srwatson case '1': 931113751Srwatson if (label_chunk_info[here].type == PART_FILESYSTEM) { 932113751Srwatson PartInfo *pi = 933113751Srwatson ((PartInfo *)label_chunk_info[here].c->private_data); 934113751Srwatson 935113751Srwatson if ((pi != NULL) && 936113751Srwatson (pi->newfs_type == NEWFS_UFS)) { 937113751Srwatson pi->newfs_data.newfs_ufs.ufs1 = true; 938113751Srwatson } else 939113751Srwatson msg = MSG_NOT_APPLICABLE; 940113751Srwatson } else 941113751Srwatson msg = MSG_NOT_APPLICABLE; 942113751Srwatson break; 943113751Srwatson break; 944113751Srwatson 945107565Srwatson case '2': 946107565Srwatson if (label_chunk_info[here].type == PART_FILESYSTEM) { 947107565Srwatson PartInfo *pi = 948107565Srwatson ((PartInfo *)label_chunk_info[here].c->private_data); 949107565Srwatson 950107565Srwatson if ((pi != NULL) && 951107565Srwatson (pi->newfs_type == NEWFS_UFS)) { 952113751Srwatson pi->newfs_data.newfs_ufs.ufs1 = false; 953107565Srwatson } else 954107565Srwatson msg = MSG_NOT_APPLICABLE; 955107565Srwatson } else 956107565Srwatson msg = MSG_NOT_APPLICABLE; 957107565Srwatson break; 958107565Srwatson break; 959107565Srwatson 96010882Speter case 'A': 96110882Speter if (label_chunk_info[here].type != PART_SLICE) { 96215440Sjkh msg = "You can only do this in a disk slice (at top of screen)"; 96310882Speter break; 96410882Speter } 96587557Sdillon /* 96687557Sdillon * Generate standard partitions automatically. If we do not 96787557Sdillon * have sufficient space we attempt to scale-down the size 96887557Sdillon * of the partitions within certain bounds. 96987557Sdillon */ 97087557Sdillon { 97187557Sdillon int perc; 97287557Sdillon int req = 0; 97312661Speter 97487557Sdillon for (perc = 100; perc > 0; perc -= 5) { 97587557Sdillon req = 0; /* reset for each loop */ 97687557Sdillon if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL) 97717362Sjkh break; 97815440Sjkh } 97987557Sdillon if (msg) { 98087557Sdillon if (req) { 981234737Sdim msgConfirm("%s", msg); 98218619Sjkh clear_wins(); 98387557Sdillon msg = NULL; 98417362Sjkh } 98515440Sjkh } 98610882Speter } 98715440Sjkh break; 98810882Speter 9898549Sjkh case 'C': 9908549Sjkh if (label_chunk_info[here].type != PART_SLICE) { 9918549Sjkh msg = "You can only do this in a master partition (see top of screen)"; 9928549Sjkh break; 9938549Sjkh } 9948549Sjkh sz = space_free(label_chunk_info[here].c); 9958669Sphk if (sz <= FS_MIN_SIZE) { 99612661Speter msg = "Not enough space to create an additional FreeBSD partition"; 9978669Sphk break; 9988669Sphk } 99915440Sjkh else { 100018744Sjkh char *val; 1001127081Sjhb daddr_t size; 1002209235Sbrucec long double dsize; 10038702Sjkh struct chunk *tmp; 10048820Sjkh char osize[80]; 10058702Sjkh u_long flags = 0; 10068549Sjkh 1007129259Sgrehan#ifdef __powerpc__ 1008129259Sgrehan /* Always use the maximum size for apple partitions */ 1009129259Sgrehan if (label_chunk_info[here].c->type == apple) 1010129259Sgrehan size = sz; 1011129259Sgrehan else { 1012129259Sgrehan#endif 1013127081Sjhb sprintf(osize, "%jd", (intmax_t)sz); 101418619Sjkh val = msgGetInput(osize, 101557617Sjkh "Please specify the partition size in blocks or append a trailing G for\n" 1016122021Smarcel#ifdef __ia64__ 1017122021Smarcel "gigabytes, M for megabytes.\n" 1018122021Smarcel#else 101957617Sjkh "gigabytes, M for megabytes, or C for cylinders.\n" 1020122021Smarcel#endif 1021127081Sjhb "%jd blocks (%jdMB) are free.", 1022127081Sjhb (intmax_t)sz, (intmax_t)sz / ONE_MEG); 1023209235Sbrucec if (!val || (dsize = strtold(val, &cp)) <= 0) { 102418619Sjkh clear_wins(); 10258702Sjkh break; 102618619Sjkh } 10278549Sjkh 10288751Sjkh if (*cp) { 10298751Sjkh if (toupper(*cp) == 'M') 1030209235Sbrucec size = (daddr_t) (dsize * ONE_MEG); 103157617Sjkh else if (toupper(*cp) == 'G') 1032209235Sbrucec size = (daddr_t) (dsize * ONE_GIG); 1033121890Smarcel#ifndef __ia64__ 10348751Sjkh else if (toupper(*cp) == 'C') 1035209235Sbrucec size = (daddr_t) dsize * (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect); 1036121890Smarcel#endif 1037209235Sbrucec else 1038209235Sbrucec size = (daddr_t) dsize; 1039210381Sbrucec } else { 1040210381Sbrucec size = (daddr_t) dsize; 10418751Sjkh } 1042210381Sbrucec 1043209235Sbrucec if (size < FS_MIN_SIZE) { 10448820Sjkh msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG); 104518619Sjkh clear_wins(); 10468820Sjkh break; 10478820Sjkh } 1048129259Sgrehan#ifdef __powerpc__ 1049129259Sgrehan } 1050129259Sgrehan#endif 10518702Sjkh type = get_partition_type(); 105218619Sjkh if (type == PART_NONE) { 105318619Sjkh clear_wins(); 105418619Sjkh beep(); 10558669Sphk break; 105618619Sjkh } 10578669Sphk 1058122021Smarcel if (type == PART_FILESYSTEM || type == PART_EFI) { 1059133106Smarcel if ((p = get_mountpoint(type, NULL)) == NULL) { 106018619Sjkh clear_wins(); 106118619Sjkh beep(); 10628702Sjkh break; 106318619Sjkh } 1064122021Smarcel else if (!strcmp(p->mountpoint, "/")) { 1065122021Smarcel if (type != PART_FILESYSTEM) { 1066122021Smarcel clear_wins(); 1067122021Smarcel beep(); 1068122021Smarcel break; 1069122021Smarcel } 1070122021Smarcel else 1071122021Smarcel flags |= CHUNK_IS_ROOT; 1072122021Smarcel } 10738702Sjkh else 10748702Sjkh flags &= ~CHUNK_IS_ROOT; 107518619Sjkh } 107618619Sjkh else 10778702Sjkh p = NULL; 10788702Sjkh 107976237Sjkh if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) { 108076237Sjkh msgConfirm("Warning: This is smaller than the recommended size for a\n" 108176237Sjkh "root partition. For a variety of reasons, root\n" 108276237Sjkh "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE); 10838672Sjkh } 10848751Sjkh tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1085122021Smarcel label_chunk_info[here].c, size, 1086122021Smarcel#ifdef __ia64__ 1087122021Smarcel (type == PART_EFI) ? efi : part, 1088122021Smarcel (type == PART_EFI) ? 0 : (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 1089122021Smarcel#else 1090122021Smarcel part, (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, 1091122021Smarcel#endif 1092122021Smarcel flags); 10938702Sjkh if (!tmp) { 10948702Sjkh msgConfirm("Unable to create the partition. Too big?"); 109518619Sjkh clear_wins(); 10968672Sjkh break; 10978672Sjkh } 109879678Sobrien 1099106826Sjhb tmp->private_data = p; 11008702Sjkh tmp->private_free = safe_free; 110174156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 110243685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 110330345Sjkh record_label_chunks(devs, dev); 110418619Sjkh clear_wins(); 110579678Sobrien /* This is where we assign focus to new label so it shows. */ 110629249Sjkh { 110729249Sjkh int i; 110829249Sjkh label_focus = -1; 110929249Sjkh for (i = 0; label_chunk_info[i].c; ++i) { 111029249Sjkh if (label_chunk_info[i].c == tmp) { 111129249Sjkh label_focus = i; 111229249Sjkh break; 111329249Sjkh } 111429249Sjkh } 111529249Sjkh if (label_focus == -1) 111629249Sjkh label_focus = i - 1; 111729249Sjkh } 11188549Sjkh } 11198549Sjkh break; 11208549Sjkh 112117397Sjkh case KEY_DC: 112288996Sdillon case 'R': /* recover space (delete w/ recover) */ 112388996Sdillon /* 112488996Sdillon * Delete the partition w/ space recovery. 112588996Sdillon */ 112688996Sdillon rflags = DELCHUNK_RECOVER; 112788996Sdillon /* fall through */ 11288549Sjkh case 'D': /* delete */ 11298549Sjkh if (label_chunk_info[here].type == PART_SLICE) { 11308549Sjkh msg = MSG_NOT_APPLICABLE; 11318549Sjkh break; 11328549Sjkh } 11338549Sjkh else if (label_chunk_info[here].type == PART_FAT) { 11348705Sjkh msg = "Use the Disk Partition Editor to delete DOS partitions"; 11358549Sjkh break; 11368549Sjkh } 113788996Sdillon Delete_Chunk2(label_chunk_info[here].c->disk, label_chunk_info[here].c, rflags); 113874156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 113943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 114030345Sjkh record_label_chunks(devs, dev); 11418549Sjkh break; 11428549Sjkh 11438549Sjkh case 'M': /* mount */ 11448549Sjkh switch(label_chunk_info[here].type) { 11458549Sjkh case PART_SLICE: 11468549Sjkh msg = MSG_NOT_APPLICABLE; 11478549Sjkh break; 11488549Sjkh 11498549Sjkh case PART_SWAP: 11508549Sjkh msg = "You don't need to specify a mountpoint for a swap partition."; 11518549Sjkh break; 11528549Sjkh 11538556Sjkh case PART_FAT: 1154121890Smarcel case PART_EFI: 11558549Sjkh case PART_FILESYSTEM: 115614793Sjoerg oldp = label_chunk_info[here].c->private_data; 1157133106Smarcel p = get_mountpoint(label_chunk_info[here].type, label_chunk_info[here].c); 11588549Sjkh if (p) { 11599202Srgrimes if (!oldp) 1160107565Srwatson p->do_newfs = FALSE; 1161121890Smarcel if ((label_chunk_info[here].type == PART_FAT || 1162121890Smarcel label_chunk_info[here].type == PART_EFI) && 1163121890Smarcel (!strcmp(p->mountpoint, "/") || 1164121890Smarcel !strcmp(p->mountpoint, "/usr") || 1165121890Smarcel !strcmp(p->mountpoint, "/var"))) { 11668722Sjkh msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint); 11678722Sjkh strcpy(p->mountpoint, "/bogus"); 11688722Sjkh } 11698549Sjkh } 117074156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 117143685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 117230345Sjkh record_label_chunks(devs, dev); 117318636Sjkh clear_wins(); 11748549Sjkh break; 11758549Sjkh 11768549Sjkh default: 11778549Sjkh msgFatal("Bogus partition under cursor???"); 11788549Sjkh break; 11798549Sjkh } 11808549Sjkh break; 11818549Sjkh 11828549Sjkh case 'N': /* Set newfs options */ 118314793Sjoerg if (label_chunk_info[here].c->private_data && 1184107565Srwatson ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs) 1185107565Srwatson getNewfsOptionalArguments( 1186107565Srwatson label_chunk_info[here].c->private_data); 11878549Sjkh else 11888549Sjkh msg = MSG_NOT_APPLICABLE; 118918636Sjkh clear_wins(); 11908549Sjkh break; 11918549Sjkh 119274086Sjkh case 'S': /* Toggle soft updates flag */ 119374086Sjkh if (label_chunk_info[here].type == PART_FILESYSTEM) { 119474086Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 1195107565Srwatson if (pi != NULL && 1196107565Srwatson pi->newfs_type == NEWFS_UFS) 1197107565Srwatson pi->newfs_data.newfs_ufs.softupdates = 1198107565Srwatson !pi->newfs_data.newfs_ufs.softupdates; 119974086Sjkh else 120074086Sjkh msg = MSG_NOT_APPLICABLE; 120174086Sjkh } 120274156Sjkh else 120374156Sjkh msg = MSG_NOT_APPLICABLE; 120474086Sjkh break; 120574086Sjkh 12068549Sjkh case 'T': /* Toggle newfs state */ 1207133106Smarcel if ((label_chunk_info[here].type == PART_FILESYSTEM || 1208133106Smarcel label_chunk_info[here].type == PART_EFI) && 120989968Smurray (label_chunk_info[here].c->private_data)) { 121023729Sjkh PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data); 1211107565Srwatson if (!pi->do_newfs) 121287581Sdillon label_chunk_info[here].c->flags |= CHUNK_NEWFS; 121387581Sdillon else 121487581Sdillon label_chunk_info[here].c->flags &= ~CHUNK_NEWFS; 121587581Sdillon 121623729Sjkh label_chunk_info[here].c->private_data = 1217133106Smarcel new_part(label_chunk_info[here].type, pi ? pi->mountpoint : NULL, pi ? !pi->do_newfs 1218107565Srwatson : TRUE); 1219107565Srwatson if (pi != NULL && 1220107565Srwatson pi->newfs_type == NEWFS_UFS) { 1221107565Srwatson PartInfo *pi_new = label_chunk_info[here].c->private_data; 1222107565Srwatson 1223107565Srwatson pi_new->newfs_data.newfs_ufs = pi->newfs_data.newfs_ufs; 1224107565Srwatson } 122523729Sjkh safe_free(pi); 122623729Sjkh label_chunk_info[here].c->private_free = safe_free; 122774156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 122843685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 122918619Sjkh } 12308549Sjkh else 12318549Sjkh msg = MSG_NOT_APPLICABLE; 12328549Sjkh break; 12338549Sjkh 12348820Sjkh case 'U': 123512661Speter clear(); 123674156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 123718744Sjkh msgConfirm("You've already written out your changes -\n" 123818744Sjkh "it's too late to undo!"); 123918744Sjkh } 124070005Sjkh else if (!msgNoYes("Are you SURE you want to Undo everything?")) { 124118744Sjkh variable_unset(DISK_PARTITIONED); 124218744Sjkh variable_unset(DISK_LABELLED); 124318744Sjkh for (i = 0; devs[i]; i++) { 124418744Sjkh Disk *d; 124512661Speter 124618744Sjkh if (!devs[i]->enabled) 124718744Sjkh continue; 124818744Sjkh else if ((d = Open_Disk(devs[i]->name)) != NULL) { 124918744Sjkh Free_Disk(devs[i]->private); 125018744Sjkh devs[i]->private = d; 1251107341Sjhb#ifdef WITH_SLICES 125230345Sjkh diskPartition(devs[i]); 1253107341Sjhb#endif 125418744Sjkh } 12558824Sjkh } 125630345Sjkh record_label_chunks(devs, dev); 12578824Sjkh } 125818636Sjkh clear_wins(); 12598824Sjkh break; 12608820Sjkh 12618549Sjkh case 'W': 126274156Sjkh if (!variable_cmp(DISK_LABELLED, "written")) { 126318744Sjkh msgConfirm("You've already written out your changes - if you\n" 126474156Sjkh "wish to overwrite them, you'll have to restart\n" 1265178946Sobrien "%s first.", ProgName); 126618744Sjkh } 126770005Sjkh else if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n" 126818687Sjkh "installation. If you are installing FreeBSD for the first time\n" 126918687Sjkh "then you should simply type Q when you're finished here and your\n" 127018687Sjkh "changes will be committed in one batch automatically at the end of\n" 127118687Sjkh "these questions.\n\n" 127218687Sjkh "Are you absolutely sure you want to do this now?")) { 127343685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 127412661Speter diskLabelCommit(NULL); 127512661Speter } 127618636Sjkh clear_wins(); 127710882Speter break; 127810882Speter 1279107565Srwatson case 'Z': /* Set newfs command line */ 1280107565Srwatson if (label_chunk_info[here].c->private_data && 1281107565Srwatson ((PartInfo *)label_chunk_info[here].c->private_data)->do_newfs) 1282107565Srwatson getNewfsCmd(label_chunk_info[here].c->private_data); 1283107565Srwatson else 1284107565Srwatson msg = MSG_NOT_APPLICABLE; 1285107565Srwatson clear_wins(); 1286107565Srwatson break; 1287107565Srwatson 1288121864Smarcel#ifndef __ia64__ 128910882Speter case '|': 1290195863Strasz if (!msgNoYes("Are you sure you want to go into Expert mode?\n\n" 129112661Speter "This is an entirely undocumented feature which you are not\n" 129212661Speter "expected to understand!")) { 12938549Sjkh int i; 12948549Sjkh Device **devs; 12958549Sjkh 12968549Sjkh dialog_clear(); 12978549Sjkh end_dialog(); 12988549Sjkh DialogActive = FALSE; 12998549Sjkh devs = deviceFind(NULL, DEVICE_TYPE_DISK); 13008549Sjkh if (!devs) { 130112661Speter msgConfirm("Can't find any disk devices!"); 13028549Sjkh break; 13038549Sjkh } 13048668Sphk for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) { 13058613Sjkh if (devs[i]->enabled) 13068613Sjkh slice_wizard(((Disk *)devs[i]->private)); 13078613Sjkh } 130874156Sjkh if (variable_cmp(DISK_LABELLED, "written")) 130943685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 13108665Sphk DialogActive = TRUE; 131130345Sjkh record_label_chunks(devs, dev); 131218636Sjkh clear_wins(); 13138549Sjkh } 13148549Sjkh else 13158549Sjkh msg = "A most prudent choice!"; 13168549Sjkh break; 1317121864Smarcel#endif 13188549Sjkh 131921698Sjkh case '\033': /* ESC */ 13209202Srgrimes case 'Q': 13218549Sjkh labeling = FALSE; 13228549Sjkh break; 13238549Sjkh 13248549Sjkh default: 13258549Sjkh beep(); 132617362Sjkh sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key); 132717362Sjkh msg = _msg; 13288549Sjkh break; 13298549Sjkh } 133029633Sjkh if (label_chunk_info[here].type == PART_SLICE) 133129633Sjkh pslice_focus = here; 133229633Sjkh else 133329633Sjkh label_focus = here; 13348549Sjkh } 133554587Sjkh restorescr(w); 133654587Sjkh return DITEM_SUCCESS; 13378549Sjkh} 133826456Sjkh 1339127081Sjhbstatic __inline daddr_t 1340127081Sjhbrequested_part_size(char *varName, daddr_t nom, int def, int perc) 134187557Sdillon{ 134287557Sdillon char *cp; 1343127081Sjhb daddr_t sz; 134487557Sdillon 134598018Sjhb if ((cp = variable_get(varName)) != NULL) 1346127081Sjhb sz = strtoimax(cp, NULL, 0); 134787557Sdillon else 134887557Sdillon sz = nom + (def - nom) * perc / 100; 134987557Sdillon return(sz * ONE_MEG); 135087557Sdillon} 135187557Sdillon 135287557Sdillon/* 135387557Sdillon * Attempt to auto-label the disk. 'perc' (0-100) scales 135487557Sdillon * the size of the various partitions within appropriate 135587557Sdillon * bounds (NOMINAL through DEFAULT sizes). The procedure 135687557Sdillon * succeeds of NULL is returned. A non-null return message 135787557Sdillon * is either a failure-status message (*req == 0), or 135887557Sdillon * a confirmation requestor (*req == 1). *req is 0 on 135987557Sdillon * entry to this call. 136087557Sdillon * 1361149136Scperciva * As a special exception to the usual sizing rules, /var is given 1362149136Scperciva * additional space equal to the amount of physical memory present 1363149136Scperciva * if perc == 100 in order to ensure that users with large hard drives 1364149136Scperciva * will have enough space to store a crashdump in /var/crash. 1365149136Scperciva * 136687583Sdillon * We autolabel the following partitions: /, swap, /var, /tmp, /usr, 136787557Sdillon * and /home. /home receives any extra left over disk space. 136887557Sdillon */ 136987557Sdillonstatic char * 137087557Sdillontry_auto_label(Device **devs, Device *dev, int perc, int *req) 137187557Sdillon{ 1372127081Sjhb daddr_t sz; 1373133241Smarcel Chunk *AutoHome, *AutoRoot, *AutoSwap; 1374133241Smarcel Chunk *AutoTmp, *AutoUsr, *AutoVar; 1375133246Smarcel#ifdef __ia64__ 1376133246Smarcel Chunk *AutoEfi; 1377133246Smarcel#endif 137887557Sdillon int mib[2]; 1379106348Stmm unsigned long physmem; 138087557Sdillon size_t size; 138187557Sdillon char *msg = NULL; 138287557Sdillon 138387557Sdillon sz = space_free(label_chunk_info[here].c); 138487557Sdillon if (sz <= FS_MIN_SIZE) 138587557Sdillon return("Not enough free space to create a new partition in the slice"); 138687557Sdillon 1387133241Smarcel (void)checkLabels(FALSE); 1388133241Smarcel AutoHome = AutoRoot = AutoSwap = NULL; 1389133241Smarcel AutoTmp = AutoUsr = AutoVar = NULL; 1390133246Smarcel 1391133246Smarcel#ifdef __ia64__ 1392133246Smarcel AutoEfi = NULL; 1393133246Smarcel if (EfiChunk == NULL) { 1394194953Sjhb sz = 400 * ONE_MEG; 1395133246Smarcel AutoEfi = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 1396133246Smarcel label_chunk_info[here].c, sz, efi, 0, 0); 1397133246Smarcel if (AutoEfi == NULL) { 1398133246Smarcel *req = 1; 1399133246Smarcel msg = "Unable to create the EFI system partition. Too big?"; 1400133246Smarcel goto done; 1401133246Smarcel } 1402133246Smarcel AutoEfi->private_data = new_part(PART_EFI, "/efi", TRUE); 1403133246Smarcel AutoEfi->private_free = safe_free; 1404133246Smarcel AutoEfi->flags |= CHUNK_NEWFS; 1405133246Smarcel record_label_chunks(devs, dev); 1406133246Smarcel } 1407133246Smarcel#endif 1408133246Smarcel 1409133241Smarcel if (RootChunk == NULL) { 141087557Sdillon sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc); 141187557Sdillon 1412133241Smarcel AutoRoot = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 141387581Sdillon label_chunk_info[here].c, sz, part, 141487581Sdillon FS_BSDFFS, CHUNK_IS_ROOT | CHUNK_AUTO_SIZE); 1415133241Smarcel if (!AutoRoot) { 141687557Sdillon *req = 1; 141787557Sdillon msg = "Unable to create the root partition. Too big?"; 141887557Sdillon goto done; 141987557Sdillon } 1420133241Smarcel AutoRoot->private_data = new_part(PART_FILESYSTEM, "/", TRUE); 1421133241Smarcel AutoRoot->private_free = safe_free; 1422133241Smarcel AutoRoot->flags |= CHUNK_NEWFS; 142387557Sdillon record_label_chunks(devs, dev); 142487557Sdillon } 1425133241Smarcel if (SwapChunk == NULL) { 142687557Sdillon sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc); 142787557Sdillon if (sz == 0) { 1428127081Sjhb daddr_t nom; 1429127081Sjhb daddr_t def; 143087557Sdillon 143187557Sdillon mib[0] = CTL_HW; 143287557Sdillon mib[1] = HW_PHYSMEM; 143387557Sdillon size = sizeof physmem; 143487557Sdillon sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 143587557Sdillon def = 2 * (int)(physmem / 512); 143687557Sdillon if (def < SWAP_MIN_SIZE * ONE_MEG) 143787557Sdillon def = SWAP_MIN_SIZE * ONE_MEG; 143887557Sdillon if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG) 143987557Sdillon def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG; 1440109827Sdillon nom = (int)(physmem / 512) / 8; 144187557Sdillon sz = nom + (def - nom) * perc / 100; 144287557Sdillon } 1443133241Smarcel AutoSwap = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 144487581Sdillon label_chunk_info[here].c, sz, part, 144587581Sdillon FS_SWAP, CHUNK_AUTO_SIZE); 1446133241Smarcel if (!AutoSwap) { 144787557Sdillon *req = 1; 144887557Sdillon msg = "Unable to create the swap partition. Too big?"; 144987557Sdillon goto done; 145087557Sdillon } 1451133241Smarcel AutoSwap->private_data = 0; 1452133241Smarcel AutoSwap->private_free = safe_free; 145387557Sdillon record_label_chunks(devs, dev); 145487557Sdillon } 1455133241Smarcel if (VarChunk == NULL) { 1456149136Scperciva /* Work out how much extra space we want for a crash dump */ 1457149136Scperciva unsigned long crashdumpsz; 145887557Sdillon 1459149136Scperciva mib[0] = CTL_HW; 1460149136Scperciva mib[1] = HW_PHYSMEM; 1461149136Scperciva size = sizeof(physmem); 1462149136Scperciva sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0); 1463149136Scperciva 1464149136Scperciva if (perc == 100) 1465149136Scperciva crashdumpsz = physmem / 1048576; 1466149136Scperciva else 1467149136Scperciva crashdumpsz = 0; 1468149136Scperciva 1469149136Scperciva sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, \ 1470149136Scperciva VAR_DEFAULT_SIZE + crashdumpsz, perc); 1471149136Scperciva 1472133241Smarcel AutoVar = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 147387581Sdillon label_chunk_info[here].c, sz, part, 147487581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 1475133241Smarcel if (!AutoVar) { 147687557Sdillon *req = 1; 147787557Sdillon msg = "Not enough free space for /var - you will need to\n" 147887557Sdillon "partition your disk manually with a custom install!"; 147987557Sdillon goto done; 148087557Sdillon } 1481133241Smarcel AutoVar->private_data = new_part(PART_FILESYSTEM, "/var", TRUE); 1482133241Smarcel AutoVar->private_free = safe_free; 1483133241Smarcel AutoVar->flags |= CHUNK_NEWFS; 148487557Sdillon record_label_chunks(devs, dev); 148587557Sdillon } 1486133241Smarcel if (TmpChunk == NULL && !variable_get(VAR_NO_TMP)) { 148787583Sdillon sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc); 148887557Sdillon 1489133241Smarcel AutoTmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 149087581Sdillon label_chunk_info[here].c, sz, part, 149187581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 1492133241Smarcel if (!AutoTmp) { 149387557Sdillon *req = 1; 149487583Sdillon msg = "Not enough free space for /tmp - you will need to\n" 149587557Sdillon "partition your disk manually with a custom install!"; 149687557Sdillon goto done; 149787557Sdillon } 1498133241Smarcel AutoTmp->private_data = new_part(PART_FILESYSTEM, "/tmp", TRUE); 1499133241Smarcel AutoTmp->private_free = safe_free; 1500133241Smarcel AutoTmp->flags |= CHUNK_NEWFS; 150187557Sdillon record_label_chunks(devs, dev); 150287557Sdillon } 1503133241Smarcel if (UsrChunk == NULL && !variable_get(VAR_NO_USR)) { 150487557Sdillon sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc); 150588996Sdillon#if AUTO_HOME == 0 1506157107Scperciva if (sz < space_free(label_chunk_info[here].c)) 150787557Sdillon sz = space_free(label_chunk_info[here].c); 150887557Sdillon#endif 150987557Sdillon if (sz) { 151087557Sdillon if (sz < (USR_MIN_SIZE * ONE_MEG)) { 151187557Sdillon *req = 1; 151287557Sdillon msg = "Not enough free space for /usr - you will need to\n" 151387557Sdillon "partition your disk manually with a custom install!"; 151487557Sdillon } 151587557Sdillon 1516133241Smarcel AutoUsr = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 151787581Sdillon label_chunk_info[here].c, sz, part, 151887581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 1519133241Smarcel if (!AutoUsr) { 152087557Sdillon msg = "Unable to create the /usr partition. Not enough space?\n" 152187557Sdillon "You will need to partition your disk manually with a custom install!"; 152287557Sdillon goto done; 152387557Sdillon } 1524133241Smarcel AutoUsr->private_data = new_part(PART_FILESYSTEM, "/usr", TRUE); 1525133241Smarcel AutoUsr->private_free = safe_free; 1526133241Smarcel AutoUsr->flags |= CHUNK_NEWFS; 152787557Sdillon record_label_chunks(devs, dev); 152887557Sdillon } 152987557Sdillon } 153088996Sdillon#if AUTO_HOME == 1 1531133241Smarcel if (HomeChunk == NULL && !variable_get(VAR_NO_HOME)) { 153287557Sdillon sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc); 153387557Sdillon if (sz < space_free(label_chunk_info[here].c)) 153487557Sdillon sz = space_free(label_chunk_info[here].c); 153587557Sdillon if (sz) { 153687557Sdillon if (sz < (HOME_MIN_SIZE * ONE_MEG)) { 153787557Sdillon *req = 1; 153887557Sdillon msg = "Not enough free space for /home - you will need to\n" 153987557Sdillon "partition your disk manually with a custom install!"; 154087557Sdillon goto done; 154187557Sdillon } 154287557Sdillon 1543133241Smarcel AutoHome = Create_Chunk_DWIM(label_chunk_info[here].c->disk, 154487581Sdillon label_chunk_info[here].c, sz, part, 154587581Sdillon FS_BSDFFS, CHUNK_AUTO_SIZE); 1546133241Smarcel if (!AutoHome) { 154787557Sdillon msg = "Unable to create the /home partition. Not enough space?\n" 154887557Sdillon "You will need to partition your disk manually with a custom install!"; 154987557Sdillon goto done; 155087557Sdillon } 1551133241Smarcel AutoHome->private_data = new_part(PART_FILESYSTEM, "/home", TRUE); 1552133241Smarcel AutoHome->private_free = safe_free; 1553133241Smarcel AutoHome->flags |= CHUNK_NEWFS; 155487557Sdillon record_label_chunks(devs, dev); 155587557Sdillon } 155687557Sdillon } 155788996Sdillon#endif 155887557Sdillon 155987557Sdillon /* At this point, we're reasonably "labelled" */ 156087557Sdillon if (variable_cmp(DISK_LABELLED, "written")) 156187557Sdillon variable_set2(DISK_LABELLED, "yes", 0); 156287557Sdillon 156387557Sdillondone: 156487557Sdillon if (msg) { 1565133241Smarcel if (AutoRoot != NULL) 1566133241Smarcel Delete_Chunk(AutoRoot->disk, AutoRoot); 1567133241Smarcel if (AutoSwap != NULL) 1568133241Smarcel Delete_Chunk(AutoSwap->disk, AutoSwap); 1569133241Smarcel if (AutoVar != NULL) 1570133241Smarcel Delete_Chunk(AutoVar->disk, AutoVar); 1571133241Smarcel if (AutoTmp != NULL) 1572133241Smarcel Delete_Chunk(AutoTmp->disk, AutoTmp); 1573133241Smarcel if (AutoUsr != NULL) 1574133241Smarcel Delete_Chunk(AutoUsr->disk, AutoUsr); 1575133241Smarcel if (AutoHome != NULL) 1576133241Smarcel Delete_Chunk(AutoHome->disk, AutoHome); 157787557Sdillon record_label_chunks(devs, dev); 157887557Sdillon } 157987557Sdillon return(msg); 158087557Sdillon} 158187557Sdillon 158226456Sjkhstatic int 158330345SjkhdiskLabelNonInteractive(Device *dev) 158426456Sjkh{ 158526456Sjkh char *cp; 158626456Sjkh PartType type; 158726456Sjkh PartInfo *p; 1588106830Sjhb u_long flags; 158926456Sjkh int i, status; 159026456Sjkh Device **devs; 159126456Sjkh Disk *d; 159254587Sjkh 159326456Sjkh status = DITEM_SUCCESS; 159426456Sjkh cp = variable_get(VAR_DISK); 159526456Sjkh if (!cp) { 159626456Sjkh msgConfirm("diskLabel: No disk selected - can't label automatically."); 159726456Sjkh return DITEM_FAILURE; 159826456Sjkh } 159926456Sjkh devs = deviceFind(cp, DEVICE_TYPE_DISK); 160026456Sjkh if (!devs) { 160126456Sjkh msgConfirm("diskLabel: No disk device %s found!", cp); 160226456Sjkh return DITEM_FAILURE; 160326456Sjkh } 160430345Sjkh if (dev) 160530345Sjkh d = dev->private; 160630345Sjkh else 160730345Sjkh d = devs[0]->private; 160830345Sjkh record_label_chunks(devs, dev); 160926456Sjkh for (i = 0; label_chunk_info[i].c; i++) { 161026456Sjkh Chunk *c1 = label_chunk_info[i].c; 161126456Sjkh 161226456Sjkh if (label_chunk_info[i].type == PART_SLICE) { 161328075Sjkh char name[512]; 1614106827Sjhb char typ[10], mpoint[50]; 1615106827Sjhb int entries; 161626456Sjkh 1617106827Sjhb for (entries = 1;; entries++) { 1618127081Sjhb intmax_t sz; 1619127081Sjhb int soft = 0; 162028075Sjkh snprintf(name, sizeof name, "%s-%d", c1->name, entries); 1621106827Sjhb if ((cp = variable_get(name)) == NULL) 1622106827Sjhb break; 1623127081Sjhb if (sscanf(cp, "%s %jd %s %d", typ, &sz, mpoint, &soft) < 3) { 1624106827Sjhb msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 1625106827Sjhb status = DITEM_FAILURE; 1626106827Sjhb break; 1627106827Sjhb } else { 1628106827Sjhb Chunk *tmp; 162926456Sjkh 1630106830Sjhb flags = 0; 1631106827Sjhb if (!strcmp(typ, "swap")) { 1632106827Sjhb type = PART_SWAP; 1633106827Sjhb strcpy(mpoint, "SWAP"); 1634106827Sjhb } else { 1635106827Sjhb type = PART_FILESYSTEM; 1636106827Sjhb if (!strcmp(mpoint, "/")) 1637106827Sjhb flags |= CHUNK_IS_ROOT; 1638106827Sjhb } 1639106827Sjhb if (!sz) 1640106827Sjhb sz = space_free(c1); 1641106827Sjhb if (sz > space_free(c1)) { 1642106827Sjhb msgConfirm("Not enough free space to create partition: %s", mpoint); 164326456Sjkh status = DITEM_FAILURE; 1644106827Sjhb break; 164526456Sjkh } 1646106827Sjhb if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part, 1647106827Sjhb (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) { 1648106827Sjhb msgConfirm("Unable to create from partition spec: %s. Too big?", cp); 1649106827Sjhb status = DITEM_FAILURE; 1650106827Sjhb break; 1651106827Sjhb } else { 1652107565Srwatson PartInfo *pi; 1653133106Smarcel pi = tmp->private_data = new_part(PART_FILESYSTEM, mpoint, TRUE); 1654106827Sjhb tmp->private_free = safe_free; 1655107565Srwatson pi->newfs_data.newfs_ufs.softupdates = soft; 1656218841Sbrucec if (!strcmp(typ, "ufs1")) 1657218841Sbrucec pi->newfs_data.newfs_ufs.ufs1 = TRUE; 165826456Sjkh } 165926456Sjkh } 166026456Sjkh } 1661106827Sjhb } else { 166228075Sjkh /* Must be something we can set a mountpoint for */ 166326456Sjkh cp = variable_get(c1->name); 166426456Sjkh if (cp) { 166528075Sjkh char mpoint[50], do_newfs[8]; 166626456Sjkh Boolean newfs = FALSE; 166726456Sjkh 166828075Sjkh do_newfs[0] = '\0'; 166928075Sjkh if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) { 167026456Sjkh msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp); 167126456Sjkh status = DITEM_FAILURE; 1672106828Sjhb break; 167326456Sjkh } 167428075Sjkh newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE; 167526456Sjkh if (c1->private_data) { 167626456Sjkh p = c1->private_data; 1677107565Srwatson p->do_newfs = newfs; 167826456Sjkh strcpy(p->mountpoint, mpoint); 167926456Sjkh } 168026456Sjkh else { 1681133106Smarcel c1->private_data = new_part(PART_FILESYSTEM, mpoint, newfs); 168226456Sjkh c1->private_free = safe_free; 168326456Sjkh } 168426456Sjkh if (!strcmp(mpoint, "/")) 168526456Sjkh c1->flags |= CHUNK_IS_ROOT; 168626456Sjkh else 168726456Sjkh c1->flags &= ~CHUNK_IS_ROOT; 168826456Sjkh } 168926456Sjkh } 169026456Sjkh } 169126456Sjkh if (status == DITEM_SUCCESS) 169243685Sjkh variable_set2(DISK_LABELLED, "yes", 0); 169326456Sjkh return status; 169426456Sjkh} 1695