label.c revision 88996
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 88996 2002-01-07 07:51:24Z dillon $
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
4388996Sdillon#define AUTO_HOME	0	/* do not create /home automatically */
4488996Sdillon
458549Sjkh/*
468549Sjkh * Everything to do with editing the contents of disk labels.
478549Sjkh */
488549Sjkh
498549Sjkh/* A nice message we use a lot in the disklabel editor */
508549Sjkh#define MSG_NOT_APPLICABLE	"That option is not applicable here"
518549Sjkh
528549Sjkh/* Where to start printing the freebsd slices */
538549Sjkh#define CHUNK_SLICE_START_ROW		2
548622Sjkh#define CHUNK_PART_START_ROW		11
558549Sjkh
568549Sjkh/* The smallest filesystem we're willing to create */
578702Sjkh#define FS_MIN_SIZE			ONE_MEG
588549Sjkh
5987557Sdillon/*
6087557Sdillon * Minimum partition sizes
6187557Sdillon */
6244601Sjkh#ifdef __alpha__
6345127Sjkh#define ROOT_MIN_SIZE			40
6444601Sjkh#else
6545127Sjkh#define ROOT_MIN_SIZE			30
6644601Sjkh#endif
6787557Sdillon#define SWAP_MIN_SIZE			32
6887557Sdillon#define USR_MIN_SIZE			80
6987557Sdillon#define VAR_MIN_SIZE			20
7087583Sdillon#define TMP_MIN_SIZE			20
7187557Sdillon#define HOME_MIN_SIZE			20
728549Sjkh
7387557Sdillon/*
7487557Sdillon * Swap size limit for auto-partitioning (4G).
7587557Sdillon */
7687557Sdillon#define SWAP_AUTO_LIMIT_SIZE		4096
7744601Sjkh
7887557Sdillon/*
7987557Sdillon * Default partition sizes.  If we do not have sufficient disk space
8087557Sdillon * for this configuration we scale things relative to the NOM vs DEFAULT
8187557Sdillon * sizes.  If the disk is larger then /home will get any remaining space.
8287557Sdillon */
8387557Sdillon#define ROOT_DEFAULT_SIZE		128
8487557Sdillon#define USR_DEFAULT_SIZE		3072
8587557Sdillon#define VAR_DEFAULT_SIZE		256
8687583Sdillon#define TMP_DEFAULT_SIZE		256
8787557Sdillon#define HOME_DEFAULT_SIZE		USR_DEFAULT_SIZE
8812661Speter
8987557Sdillon/*
9087557Sdillon * Nominal partition sizes.  These are used to scale the default sizes down
9187557Sdillon * when we have insufficient disk space.  If this isn't sufficient we scale
9287557Sdillon * down using the MIN sizes instead.
9387557Sdillon */
9487557Sdillon#define ROOT_NOMINAL_SIZE		128
9587557Sdillon#define USR_NOMINAL_SIZE		512
9687557Sdillon#define VAR_NOMINAL_SIZE		64
9787583Sdillon#define TMP_NOMINAL_SIZE		64
9887557Sdillon#define HOME_NOMINAL_SIZE		USR_NOMINAL_SIZE
9912661Speter
10015440Sjkh/* The bottom-most row we're allowed to scribble on */
10129249Sjkh#define CHUNK_ROW_MAX			16
10215440Sjkh
10315440Sjkh
1048549Sjkh/* All the chunks currently displayed on the screen */
1058549Sjkhstatic struct {
1068549Sjkh    struct chunk *c;
1078549Sjkh    PartType type;
1088549Sjkh} label_chunk_info[MAX_CHUNKS + 1];
1098549Sjkhstatic int here;
1108549Sjkh
11129249Sjkh/*** with this value we try to track the most recently added label ***/
11229249Sjkhstatic int label_focus = 0, pslice_focus = 0;
11329249Sjkh
11430345Sjkhstatic int diskLabel(Device *dev);
11530345Sjkhstatic int diskLabelNonInteractive(Device *dev);
11687557Sdillonstatic char *try_auto_label(Device **devs, Device *dev, int perc, int *req);
11712661Speter
11830345Sjkhstatic int
11930345SjkhlabelHook(dialogMenuItem *selected)
12030345Sjkh{
12130345Sjkh    Device **devs = NULL;
12230345Sjkh
12330345Sjkh    devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
12430345Sjkh    if (!devs) {
12530345Sjkh	msgConfirm("Unable to find disk %s!", selected->prompt);
12630345Sjkh	return DITEM_FAILURE;
12730345Sjkh    }
12830345Sjkh    /* Toggle enabled status? */
12930345Sjkh    if (!devs[0]->enabled) {
13030345Sjkh	devs[0]->enabled = TRUE;
13130345Sjkh	diskLabel(devs[0]);
13230345Sjkh    }
13330345Sjkh    else
13430345Sjkh	devs[0]->enabled = FALSE;
13554587Sjkh    return DITEM_SUCCESS;
13630345Sjkh}
13730345Sjkh
13830345Sjkhstatic int
13930345SjkhlabelCheck(dialogMenuItem *selected)
14030345Sjkh{
14130345Sjkh    Device **devs = NULL;
14230345Sjkh
14330345Sjkh    devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
14430345Sjkh    if (!devs || devs[0]->enabled == FALSE)
14530345Sjkh	return FALSE;
14630345Sjkh    return TRUE;
14730345Sjkh}
14830345Sjkh
14912661Speterint
15015091SjkhdiskLabelEditor(dialogMenuItem *self)
15112661Speter{
15230345Sjkh    DMenu *menu;
15312661Speter    Device **devs;
15430345Sjkh    int i, cnt;
15512661Speter
15630345Sjkh    i = 0;
15730345Sjkh    cnt = diskGetSelectCount(&devs);
15830345Sjkh    if (cnt == -1) {
15912661Speter	msgConfirm("No disks found!  Please verify that your disk controller is being\n"
16012661Speter		   "properly probed at boot time.  See the Hardware Guide on the\n"
16112661Speter		   "Documentation menu for clues on diagnosing this type of problem.");
16215242Sjkh	return DITEM_FAILURE;
16312661Speter    }
16430345Sjkh    else if (cnt) {
16530345Sjkh	/* Some are already selected */
16630381Sjkh	if (variable_get(VAR_NONINTERACTIVE))
16734543Sjkh	    i = diskLabelNonInteractive(NULL);
16830381Sjkh	else
16934543Sjkh	    i = diskLabel(NULL);
17012661Speter    }
17130345Sjkh    else {
17230345Sjkh	/* No disks are selected, fall-back case now */
17330345Sjkh	cnt = deviceCount(devs);
17430345Sjkh	if (cnt == 1) {
17530345Sjkh	    devs[0]->enabled = TRUE;
17630345Sjkh	    if (variable_get(VAR_NONINTERACTIVE))
17730345Sjkh		i = diskLabelNonInteractive(devs[0]);
17830345Sjkh	    else
17930345Sjkh		i = diskLabel(devs[0]);
18030345Sjkh	}
18130345Sjkh	else {
18230345Sjkh	    menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, labelHook, labelCheck);
18330345Sjkh	    if (!menu) {
18430345Sjkh		msgConfirm("No devices suitable for installation found!\n\n"
18530345Sjkh			   "Please verify that your disk controller (and attached drives)\n"
18630345Sjkh			   "were detected properly.  This can be done by pressing the\n"
18730345Sjkh			   "[Scroll Lock] key and using the Arrow keys to move back to\n"
18830345Sjkh			   "the boot messages.  Press [Scroll Lock] again to return.");
18930345Sjkh		i = DITEM_FAILURE;
19030345Sjkh	    }
19130345Sjkh	    else {
19230345Sjkh		i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE;
19330345Sjkh		free(menu);
19430345Sjkh	    }
19530345Sjkh	}
19612661Speter    }
19718744Sjkh    if (DITEM_STATUS(i) != DITEM_FAILURE) {
19874156Sjkh	if (variable_cmp(DISK_LABELLED, "written"))
19943685Sjkh	    variable_set2(DISK_LABELLED, "yes", 0);
20018744Sjkh    }
20112661Speter    return i;
20212661Speter}
20312661Speter
20412661Speterint
20515091SjkhdiskLabelCommit(dialogMenuItem *self)
20612661Speter{
20712661Speter    char *cp;
20812661Speter    int i;
20912661Speter
21012661Speter    /* Already done? */
21117025Sjkh    if ((cp = variable_get(DISK_LABELLED)) && strcmp(cp, "yes"))
21215242Sjkh	i = DITEM_SUCCESS;
21312661Speter    else if (!cp) {
21412661Speter	msgConfirm("You must assign disk labels before this option can be used.");
21515242Sjkh	i = DITEM_FAILURE;
21612661Speter    }
21712661Speter    /* The routine will guard against redundant writes, just as this one does */
21815419Sjkh    else if (DITEM_STATUS(diskPartitionWrite(self)) != DITEM_SUCCESS)
21915242Sjkh	i = DITEM_FAILURE;
22015419Sjkh    else if (DITEM_STATUS(installFilesystems(self)) != DITEM_SUCCESS)
22115242Sjkh	i = DITEM_FAILURE;
22212661Speter    else {
22312661Speter	msgInfo("All filesystem information written successfully.");
22443685Sjkh	variable_set2(DISK_LABELLED, "written", 0);
22515242Sjkh	i = DITEM_SUCCESS;
22612661Speter    }
22712661Speter    return i;
22812661Speter}
22912661Speter
2308549Sjkh/* See if we're already using a desired partition name */
2318549Sjkhstatic Boolean
2328549Sjkhcheck_conflict(char *name)
2338549Sjkh{
2348549Sjkh    int i;
2358549Sjkh
2368751Sjkh    for (i = 0; label_chunk_info[i].c; i++)
23723729Sjkh	if ((label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT)
23823729Sjkh	    && label_chunk_info[i].c->private_data
23914793Sjoerg	    && !strcmp(((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint, name))
2408549Sjkh	    return TRUE;
2418549Sjkh    return FALSE;
2428549Sjkh}
2438549Sjkh
2448549Sjkh/* How much space is in this FreeBSD slice? */
2458549Sjkhstatic int
2468549Sjkhspace_free(struct chunk *c)
2478549Sjkh{
24812661Speter    struct chunk *c1;
2498549Sjkh    int sz = c->size;
2508549Sjkh
25112661Speter    for (c1 = c->part; c1; c1 = c1->next) {
2528549Sjkh	if (c1->type != unused)
2538549Sjkh	    sz -= c1->size;
2548549Sjkh    }
2558549Sjkh    if (sz < 0)
2568549Sjkh	msgFatal("Partitions are larger than actual chunk??");
2578549Sjkh    return sz;
2588549Sjkh}
2598549Sjkh
2608549Sjkh/* Snapshot the current situation into the displayed chunks structure */
2618549Sjkhstatic void
26230345Sjkhrecord_label_chunks(Device **devs, Device *dev)
2638549Sjkh{
2648549Sjkh    int i, j, p;
2658549Sjkh    struct chunk *c1, *c2;
2668556Sjkh    Disk *d;
2678549Sjkh
2688549Sjkh    j = p = 0;
2698556Sjkh    /* First buzz through and pick up the FreeBSD slices */
2708549Sjkh    for (i = 0; devs[i]; i++) {
27130345Sjkh	if ((dev && devs[i] != dev) || !devs[i]->enabled)
2728556Sjkh	    continue;
2738556Sjkh	d = (Disk *)devs[i]->private;
2748556Sjkh	if (!d->chunks)
2758556Sjkh	    msgFatal("No chunk list found for %s!", d->name);
2768549Sjkh
2778556Sjkh	/* Put the slice entries first */
2788556Sjkh	for (c1 = d->chunks->part; c1; c1 = c1->next) {
2798549Sjkh	    if (c1->type == freebsd) {
2808549Sjkh		label_chunk_info[j].type = PART_SLICE;
2818549Sjkh		label_chunk_info[j].c = c1;
2828549Sjkh		++j;
2838549Sjkh	    }
2848549Sjkh	}
2858549Sjkh    }
28612661Speter
2878556Sjkh    /* Now run through again and get the FreeBSD partition entries */
2888556Sjkh    for (i = 0; devs[i]; i++) {
2898556Sjkh	if (!devs[i]->enabled)
2908556Sjkh	    continue;
2918556Sjkh	d = (Disk *)devs[i]->private;
2928549Sjkh	/* Then buzz through and pick up the partitions */
2938556Sjkh	for (c1 = d->chunks->part; c1; c1 = c1->next) {
2948549Sjkh	    if (c1->type == freebsd) {
2958549Sjkh		for (c2 = c1->part; c2; c2 = c2->next) {
2968549Sjkh		    if (c2->type == part) {
2978549Sjkh			if (c2->subtype == FS_SWAP)
2988549Sjkh			    label_chunk_info[j].type = PART_SWAP;
2998549Sjkh			else
3008549Sjkh			    label_chunk_info[j].type = PART_FILESYSTEM;
3018549Sjkh			label_chunk_info[j].c = c2;
3028549Sjkh			++j;
3038549Sjkh		    }
3048549Sjkh		}
3058549Sjkh	    }
3068549Sjkh	    else if (c1->type == fat) {
3078549Sjkh		label_chunk_info[j].type = PART_FAT;
3088549Sjkh		label_chunk_info[j].c = c1;
3098702Sjkh		++j;
3108549Sjkh	    }
3118549Sjkh	}
3128549Sjkh    }
3138549Sjkh    label_chunk_info[j].c = NULL;
31429249Sjkh    if (here >= j) {
3158549Sjkh	here = j  ? j - 1 : 0;
31629249Sjkh    }
3178549Sjkh}
3188549Sjkh
3198549Sjkh/* A new partition entry */
3208549Sjkhstatic PartInfo *
3218665Sphknew_part(char *mpoint, Boolean newfs, u_long size)
3228549Sjkh{
3238549Sjkh    PartInfo *ret;
3248549Sjkh
3259202Srgrimes    if (!mpoint)
3269202Srgrimes	mpoint = "/change_me";
3279202Srgrimes
3288549Sjkh    ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
32920247Sjkh    sstrncpy(ret->mountpoint, mpoint, FILENAME_MAX);
33049441Sphk    strcpy(ret->newfs_cmd, "newfs ");
33149441Sphk    strcat(ret->newfs_cmd, variable_get(VAR_NEWFS_ARGS));
3328666Sphk    ret->newfs = newfs;
33388321Sjkh    ret->soft = strcmp(mpoint, "/") ? 1 : 0;
3348669Sphk    if (!size)
33529249Sjkh	return ret;
3368549Sjkh    return ret;
3378549Sjkh}
3388549Sjkh
3398549Sjkh/* Get the mountpoint for a partition and save it away */
34012661Speterstatic PartInfo *
3418589Sjkhget_mountpoint(struct chunk *old)
3428549Sjkh{
3438549Sjkh    char *val;
3448549Sjkh    PartInfo *tmp;
3458549Sjkh
34614793Sjoerg    if (old && old->private_data)
34714793Sjoerg	tmp = old->private_data;
3488810Sjkh    else
3498810Sjkh	tmp = NULL;
3508810Sjkh    val = msgGetInput(tmp ? tmp->mountpoint : NULL, "Please specify a mount point for the partition");
3518764Sjkh    if (!val || !*val) {
3528751Sjkh	if (!old)
3538751Sjkh	    return NULL;
3548751Sjkh	else {
35514793Sjoerg	    free(old->private_data);
35614793Sjoerg	    old->private_data = NULL;
3578751Sjkh	}
3588669Sphk	return NULL;
3598751Sjkh    }
3608669Sphk
3618669Sphk    /* Is it just the same value? */
3628810Sjkh    if (tmp && !strcmp(tmp->mountpoint, val))
3638669Sphk	return NULL;
3648810Sjkh
3658810Sjkh    /* Did we use it already? */
3668669Sphk    if (check_conflict(val)) {
3678669Sphk	msgConfirm("You already have a mount point for %s assigned!", val);
3688669Sphk	return NULL;
3698549Sjkh    }
3708810Sjkh
3718810Sjkh    /* Is it bogus? */
3728669Sphk    if (*val != '/') {
3738669Sphk	msgConfirm("Mount point must start with a / character");
3748669Sphk	return NULL;
3758669Sphk    }
3768810Sjkh
3778810Sjkh    /* Is it going to be mounted on root? */
3788669Sphk    if (!strcmp(val, "/")) {
3798669Sphk	if (old)
3808669Sphk	    old->flags |= CHUNK_IS_ROOT;
3818810Sjkh    }
3828810Sjkh    else if (old)
3838669Sphk	old->flags &= ~CHUNK_IS_ROOT;
3848810Sjkh
3858810Sjkh    safe_free(tmp);
38646615Sjkh    val = string_skipwhite(string_prune(val));
3878669Sphk    tmp = new_part(val, TRUE, 0);
3888669Sphk    if (old) {
38914793Sjoerg	old->private_data = tmp;
3908669Sphk	old->private_free = safe_free;
3918669Sphk    }
3928669Sphk    return tmp;
3938549Sjkh}
3948549Sjkh
3958549Sjkh/* Get the type of the new partiton */
3968549Sjkhstatic PartType
3978549Sjkhget_partition_type(void)
3988549Sjkh{
3998549Sjkh    char selection[20];
4008669Sphk    int i;
4018549Sjkh    static unsigned char *fs_types[] = {
4028549Sjkh	"FS",
4038549Sjkh	"A file system",
4048549Sjkh	"Swap",
4058549Sjkh	"A swap partition.",
4068549Sjkh    };
40754587Sjkh    WINDOW *w = savescr();
40854587Sjkh
4098669Sphk    i = dialog_menu("Please choose a partition type",
41012661Speter		    "If you want to use this partition for swap space, select Swap.\n"
41112661Speter		    "If you want to put a filesystem on it, choose FS.",
41212661Speter		    -1, -1, 2, 2, fs_types, selection, NULL, NULL);
41354587Sjkh    restorescr(w);
4148669Sphk    if (!i) {
4158549Sjkh	if (!strcmp(selection, "FS"))
4168549Sjkh	    return PART_FILESYSTEM;
4178549Sjkh	else if (!strcmp(selection, "Swap"))
4188549Sjkh	    return PART_SWAP;
4198549Sjkh    }
4208549Sjkh    return PART_NONE;
4218549Sjkh}
4228549Sjkh
4238549Sjkh/* If the user wants a special newfs command for this, set it */
4248549Sjkhstatic void
4258549SjkhgetNewfsCmd(PartInfo *p)
4268549Sjkh{
4278549Sjkh    char *val;
4288549Sjkh
4298549Sjkh    val = msgGetInput(p->newfs_cmd,
43012661Speter		      "Please enter the newfs command and options you'd like to use in\n"
43112661Speter		      "creating this file system.");
4328549Sjkh    if (val)
43320247Sjkh	sstrncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
4348549Sjkh}
4358549Sjkh
43676299Sjkh#define MAX_MOUNT_NAME	9
4378549Sjkh
4388549Sjkh#define PART_PART_COL	0
43954014Sjkh#define PART_MOUNT_COL	10
4408549Sjkh#define PART_SIZE_COL	(PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
44149202Sbrian#define PART_NEWFS_COL	(PART_SIZE_COL + 8)
44276299Sjkh#define PART_OFF	38
4438549Sjkh
44429249Sjkh#define TOTAL_AVAIL_LINES       (10)
44529249Sjkh#define PSLICE_SHOWABLE          (4)
44629249Sjkh
44729249Sjkh
4488549Sjkh/* stick this all up on the screen */
4498549Sjkhstatic void
4508549Sjkhprint_label_chunks(void)
4518549Sjkh{
45229249Sjkh    int  i, j, srow, prow, pcol;
45329249Sjkh    int  sz;
45429249Sjkh    char clrmsg[80];
45529633Sjkh    int ChunkPartStartRow;
45629633Sjkh    WINDOW *ChunkWin;
4578549Sjkh
45829249Sjkh    /********************************************************/
45929249Sjkh    /*** These values are for controling screen resources ***/
46029249Sjkh    /*** Each label line holds up to 2 labels, so beware! ***/
46129249Sjkh    /*** strategy will be to try to always make sure the  ***/
46229249Sjkh    /*** highlighted label is in the active display area. ***/
46329249Sjkh    /********************************************************/
46429249Sjkh    int  pslice_max, label_max;
46529249Sjkh    int  pslice_count, label_count, label_focus_found, pslice_focus_found;
46629249Sjkh
4678549Sjkh    attrset(A_REVERSE);
4688549Sjkh    mvaddstr(0, 25, "FreeBSD Disklabel Editor");
4698549Sjkh    attrset(A_NORMAL);
4708549Sjkh
47129633Sjkh    /*** Count the number of parition slices ***/
47229633Sjkh    pslice_count = 0;
47329633Sjkh    for (i = 0; label_chunk_info[i].c ; i++) {
47429633Sjkh        if (label_chunk_info[i].type == PART_SLICE)
47529633Sjkh            ++pslice_count;
47629633Sjkh    }
47729633Sjkh    pslice_max = pslice_count;
47829633Sjkh
47929633Sjkh    /*** 4 line max for partition slices ***/
48029633Sjkh    if (pslice_max > PSLICE_SHOWABLE) {
48129633Sjkh        pslice_max = PSLICE_SHOWABLE;
48229633Sjkh    }
48329633Sjkh    ChunkPartStartRow = CHUNK_SLICE_START_ROW + 3 + pslice_max;
48429633Sjkh
48529633Sjkh    /*** View partition slices modulo pslice_max ***/
48629633Sjkh    label_max = TOTAL_AVAIL_LINES - pslice_max;
48729633Sjkh
4888549Sjkh    for (i = 0; i < 2; i++) {
48915440Sjkh	mvaddstr(ChunkPartStartRow - 2, PART_PART_COL + (i * PART_OFF), "Part");
49015440Sjkh	mvaddstr(ChunkPartStartRow - 1, PART_PART_COL + (i * PART_OFF), "----");
4918549Sjkh
49215440Sjkh	mvaddstr(ChunkPartStartRow - 2, PART_MOUNT_COL + (i * PART_OFF), "Mount");
49315440Sjkh	mvaddstr(ChunkPartStartRow - 1, PART_MOUNT_COL + (i * PART_OFF), "-----");
4948549Sjkh
49549202Sbrian	mvaddstr(ChunkPartStartRow - 2, PART_SIZE_COL + (i * PART_OFF) + 3, "Size");
49649202Sbrian	mvaddstr(ChunkPartStartRow - 1, PART_SIZE_COL + (i * PART_OFF) + 3, "----");
4978549Sjkh
49815440Sjkh	mvaddstr(ChunkPartStartRow - 2, PART_NEWFS_COL + (i * PART_OFF), "Newfs");
49915440Sjkh	mvaddstr(ChunkPartStartRow - 1, PART_NEWFS_COL + (i * PART_OFF), "-----");
5008549Sjkh    }
5018549Sjkh    srow = CHUNK_SLICE_START_ROW;
50215440Sjkh    prow = 0;
5038549Sjkh    pcol = 0;
5048549Sjkh
50529249Sjkh    /*** these variables indicate that the focused item is shown currently ***/
50629249Sjkh    label_focus_found = 0;
50729249Sjkh    pslice_focus_found = 0;
50829249Sjkh
50929249Sjkh    label_count = 0;
51029249Sjkh    pslice_count = 0;
51129249Sjkh    mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "          ");
51229249Sjkh    mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "          ");
51329249Sjkh
51429633Sjkh    ChunkWin = newwin(CHUNK_ROW_MAX - ChunkPartStartRow, 76, ChunkPartStartRow, 0);
51529633Sjkh
51629633Sjkh    wclear(ChunkWin);
51729633Sjkh    /*** wrefresh(ChunkWin); ***/
51829633Sjkh
5198751Sjkh    for (i = 0; label_chunk_info[i].c; i++) {
5208549Sjkh	/* Is it a slice entry displayed at the top? */
5218549Sjkh	if (label_chunk_info[i].type == PART_SLICE) {
52229249Sjkh            /*** This causes the new pslice to replace the previous display ***/
52329249Sjkh            /*** focus must remain on the most recently active pslice       ***/
52429249Sjkh            if (pslice_count == pslice_max) {
52529249Sjkh                if (pslice_focus_found) {
52629249Sjkh                    /*** This is where we can mark the more following ***/
52729249Sjkh                    attrset(A_BOLD);
52829249Sjkh                    mvprintw(CHUNK_SLICE_START_ROW + pslice_max, 0, "***MORE***");
52929249Sjkh                    attrset(A_NORMAL);
53029249Sjkh                    continue;
53129249Sjkh                }
53229249Sjkh                else {
53329249Sjkh                    /*** this is where we set the more previous ***/
53429249Sjkh                    attrset(A_BOLD);
53529249Sjkh                    mvprintw(CHUNK_SLICE_START_ROW - 1, 0, "***MORE***");
53629249Sjkh                    attrset(A_NORMAL);
53729249Sjkh                    pslice_count = 0;
53829249Sjkh                    srow = CHUNK_SLICE_START_ROW;
53929249Sjkh                }
54029249Sjkh            }
54129249Sjkh
5428549Sjkh	    sz = space_free(label_chunk_info[i].c);
54315440Sjkh	    if (i == here)
54416208Sjkh		attrset(ATTR_SELECTED);
54529249Sjkh            if (i == pslice_focus)
54629249Sjkh                pslice_focus_found = -1;
54729249Sjkh
54829249Sjkh	    mvprintw(srow++, 0,
54929249Sjkh		     "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
55029249Sjkh		     label_chunk_info[i].c->disk->name, label_chunk_info[i].c->name,
55129249Sjkh		     sz, (sz / ONE_MEG));
55215440Sjkh	    attrset(A_NORMAL);
55315440Sjkh	    clrtoeol();
55415440Sjkh	    move(0, 0);
55529633Sjkh	    /*** refresh(); ***/
55629249Sjkh            ++pslice_count;
5578549Sjkh	}
55815440Sjkh	/* Otherwise it's a DOS, swap or filesystem entry in the Chunk window */
5598549Sjkh	else {
56074086Sjkh	    char onestr[PART_OFF], num[10], *mountpoint, newfs[10];
5618549Sjkh
5628549Sjkh	    /*
5638549Sjkh	     * We copy this into a blank-padded string so that it looks like
5648549Sjkh	     * a solid bar in reverse-video
5658549Sjkh	     */
5668549Sjkh	    memset(onestr, ' ', PART_OFF - 1);
5678549Sjkh	    onestr[PART_OFF - 1] = '\0';
56829249Sjkh
56929249Sjkh            /*** Track how many labels have been displayed ***/
57029249Sjkh            if (label_count == ((label_max - 1 ) * 2)) {
57129249Sjkh                if (label_focus_found) {
57229249Sjkh                    continue;
57329249Sjkh                }
57429249Sjkh                else {
57529249Sjkh                    label_count = 0;
57629249Sjkh                    prow = 0;
57729249Sjkh                    pcol = 0;
57829249Sjkh                }
57929249Sjkh            }
58029249Sjkh
58115440Sjkh	    /* Go for two columns if we've written one full columns worth */
58229249Sjkh	    /*** if (prow == (CHUNK_ROW_MAX - ChunkPartStartRow)) ***/
58329249Sjkh            if (label_count == label_max - 1) {
5848549Sjkh		pcol = PART_OFF;
58515440Sjkh		prow = 0;
5868549Sjkh	    }
5878705Sjkh	    memcpy(onestr + PART_PART_COL, label_chunk_info[i].c->name, strlen(label_chunk_info[i].c->name));
5888549Sjkh	    /* If it's a filesystem, display the mountpoint */
58914793Sjoerg	    if (label_chunk_info[i].c->private_data
59010882Speter		&& (label_chunk_info[i].type == PART_FILESYSTEM || label_chunk_info[i].type == PART_FAT))
59114793Sjoerg	        mountpoint = ((PartInfo *)label_chunk_info[i].c->private_data)->mountpoint;
59223529Sjkh	    else if (label_chunk_info[i].type == PART_SWAP)
59323529Sjkh		mountpoint = "swap";
59410882Speter	    else
59510882Speter	        mountpoint = "<none>";
59610882Speter
59710882Speter	    /* Now display the newfs field */
59810882Speter	    if (label_chunk_info[i].type == PART_FAT)
59974086Sjkh	        strcpy(newfs, "DOS");
60074086Sjkh	    else if (label_chunk_info[i].c->private_data && label_chunk_info[i].type == PART_FILESYSTEM) {
60174086Sjkh		strcpy(newfs, "UFS");
60276299Sjkh		strcat(newfs,
60376299Sjkh		    ((PartInfo *)label_chunk_info[i].c->private_data)->soft ?
60476299Sjkh		      "+S" : "  ");
60576299Sjkh		strcat(newfs,
60676299Sjkh		    ((PartInfo *)label_chunk_info[i].c->private_data)->newfs ?
60776299Sjkh		      " Y" : " N");
60874086Sjkh	    }
60910882Speter	    else if (label_chunk_info[i].type == PART_SWAP)
61074086Sjkh		strcpy(newfs, "SWAP");
61110882Speter	    else
61274086Sjkh		strcpy(newfs, "*");
6138549Sjkh	    for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
6148549Sjkh		onestr[PART_MOUNT_COL + j] = mountpoint[j];
61549202Sbrian	    snprintf(num, 10, "%5ldMB", label_chunk_info[i].c->size ? label_chunk_info[i].c->size / ONE_MEG : 0);
6168549Sjkh	    memcpy(onestr + PART_SIZE_COL, num, strlen(num));
6178549Sjkh	    memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
6188549Sjkh	    onestr[PART_NEWFS_COL + strlen(newfs)] = '\0';
61929633Sjkh            if (i == label_focus) {
62029633Sjkh                label_focus_found = -1;
62129633Sjkh                wattrset(ChunkWin, A_BOLD);
62229633Sjkh            }
62315440Sjkh	    if (i == here)
62416208Sjkh		wattrset(ChunkWin, ATTR_SELECTED);
62529249Sjkh
62674086Sjkh            /*** lazy man's way of expensively padding this string ***/
62774086Sjkh            while (strlen(onestr) < 37)
62829249Sjkh                strcat(onestr, " ");
62929249Sjkh
63015440Sjkh	    mvwaddstr(ChunkWin, prow, pcol, onestr);
63115440Sjkh	    wattrset(ChunkWin, A_NORMAL);
63215440Sjkh	    move(0, 0);
6338549Sjkh	    ++prow;
63429249Sjkh            ++label_count;
6358549Sjkh	}
6368549Sjkh    }
63729249Sjkh
63829249Sjkh    /*** this will erase all the extra stuff ***/
63929249Sjkh    memset(clrmsg, ' ', 37);
64029249Sjkh    clrmsg[37] = '\0';
64129249Sjkh
64229249Sjkh    while (pslice_count < pslice_max) {
64329249Sjkh        mvprintw(srow++, 0, clrmsg);
64429249Sjkh        clrtoeol();
64529249Sjkh        ++pslice_count;
64629249Sjkh    }
64729633Sjkh    while (label_count < (2 * (label_max - 1))) {
64829633Sjkh        mvwaddstr(ChunkWin, prow++, pcol, clrmsg);
64929633Sjkh	++label_count;
65029633Sjkh	if (prow == (label_max - 1)) {
65129633Sjkh	    prow = 0;
65229633Sjkh	    pcol = PART_OFF;
65329633Sjkh	}
65429249Sjkh    }
65529633Sjkh    refresh();
65629633Sjkh    wrefresh(ChunkWin);
6578549Sjkh}
6588549Sjkh
6598549Sjkhstatic void
66018619Sjkhprint_command_summary(void)
6618549Sjkh{
6628820Sjkh    mvprintw(17, 0, "The following commands are valid here (upper or lower case):");
66374086Sjkh    mvprintw(18, 0, "C = Create        D = Delete   M = Mount pt.");
66415440Sjkh    if (!RunningAsInit)
66574086Sjkh	mvprintw(18, 47, "W = Write");
66674086Sjkh    mvprintw(19, 0, "N = Newfs Opts    Q = Finish   S = Toggle SoftUpdates");
66788996Sdillon    mvprintw(20, 0, "T = Toggle Newfs  U = Undo     A = Auto Defaults    R = Delete+Merge");
66815695Sjkh    mvprintw(22, 0, "Use F1 or ? to get more help, arrow keys to select.");
6698549Sjkh    move(0, 0);
6708549Sjkh}
6718549Sjkh
67218619Sjkhstatic void
67318619Sjkhclear_wins(void)
67418619Sjkh{
67529633Sjkh    extern void print_label_chunks();
67618619Sjkh    clear();
67729633Sjkh    print_label_chunks();
67818619Sjkh}
67918619Sjkh
68043392Sjkh#ifdef __alpha__
68143392Sjkh
68243392Sjkh/*
68343392Sjkh * If there isn't a freebsd chunk already (i.e. there is no label),
68443392Sjkh * dedicate the disk.
68543392Sjkh */
68643392Sjkhstatic void
68743392Sjkhmaybe_dedicate(Disk* d)
68843392Sjkh{
68943392Sjkh    struct chunk *c;
69043392Sjkh
69143392Sjkh    for (c = d->chunks->part; c; c = c->next) {
69243392Sjkh	if (c->type == freebsd)
69343392Sjkh	    break;
69443392Sjkh    }
69543392Sjkh
69643392Sjkh    if (!c) {
69743392Sjkh	msgDebug("dedicating disk");
69843392Sjkh	All_FreeBSD(d, 1);
69943392Sjkh    }
70043392Sjkh}
70143392Sjkh
70243392Sjkh#endif
70343392Sjkh
70412661Speterstatic int
70530345SjkhdiskLabel(Device *dev)
7068549Sjkh{
70718619Sjkh    int sz, key = 0;
7088549Sjkh    Boolean labeling;
7098549Sjkh    char *msg = NULL;
7109202Srgrimes    PartInfo *p, *oldp;
7118549Sjkh    PartType type;
7128824Sjkh    Device **devs;
71342386Sjkh#ifdef __alpha__
71442386Sjkh    int i;
71542386Sjkh#endif
71654587Sjkh    WINDOW *w = savescr();
7178549Sjkh
71829628Sjkh    label_focus = 0;
71929628Sjkh    pslice_focus = 0;
72029633Sjkh    here = 0;
72130345Sjkh
72212661Speter    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
72312661Speter    if (!devs) {
72412661Speter	msgConfirm("No disks found!");
72554587Sjkh	restorescr(w);
72615242Sjkh	return DITEM_FAILURE;
72712661Speter    }
7288549Sjkh    labeling = TRUE;
7298549Sjkh    keypad(stdscr, TRUE);
73042386Sjkh#ifdef __alpha__
73142386Sjkh    for (i = 0; devs[i]; i++) {
73243392Sjkh	maybe_dedicate((Disk*) devs[i]->private);
73342386Sjkh    }
73442386Sjkh#endif
73530345Sjkh    record_label_chunks(devs, dev);
7368549Sjkh
73718619Sjkh    clear();
7388549Sjkh    while (labeling) {
73918744Sjkh	char *cp;
74088996Sdillon	int rflags = DELCHUNK_NORMAL;
74118744Sjkh
7428549Sjkh	print_label_chunks();
74318619Sjkh	print_command_summary();
7448549Sjkh	if (msg) {
74515695Sjkh	    attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
74612661Speter	    clrtoeol();
7478549Sjkh	    beep();
7488549Sjkh	    msg = NULL;
7498549Sjkh	}
75015442Sjkh	else {
75115442Sjkh	    move(23, 0);
75215442Sjkh	    clrtoeol();
75315442Sjkh	}
75418744Sjkh
75518619Sjkh	refresh();
75617397Sjkh	key = getch();
75717397Sjkh	switch (toupper(key)) {
75815440Sjkh	    int i;
75917362Sjkh	    static char _msg[40];
7608549Sjkh
7618751Sjkh	case '\014':	/* ^L */
76218619Sjkh	    clear_wins();
76318619Sjkh	    break;
7648751Sjkh
76521698Sjkh	case '\020':	/* ^P */
7668549Sjkh	case KEY_UP:
7678549Sjkh	case '-':
7688549Sjkh	    if (here != 0)
7698549Sjkh		--here;
7708751Sjkh	    else
7718751Sjkh		while (label_chunk_info[here + 1].c)
7728751Sjkh		    ++here;
7738549Sjkh	    break;
7748549Sjkh
77521698Sjkh	case '\016':	/* ^N */
7768549Sjkh	case KEY_DOWN:
7778549Sjkh	case '+':
7788549Sjkh	case '\r':
7798549Sjkh	case '\n':
7808751Sjkh	    if (label_chunk_info[here + 1].c)
7818549Sjkh		++here;
7828751Sjkh	    else
7838751Sjkh		here = 0;
7848549Sjkh	    break;
7858549Sjkh
7868549Sjkh	case KEY_HOME:
7878549Sjkh	    here = 0;
7888549Sjkh	    break;
7898549Sjkh
7908549Sjkh	case KEY_END:
7918751Sjkh	    while (label_chunk_info[here + 1].c)
7928549Sjkh		++here;
7938549Sjkh	    break;
7948549Sjkh
7958549Sjkh	case KEY_F(1):
7968549Sjkh	case '?':
79712661Speter	    systemDisplayHelp("partition");
79818619Sjkh	    clear_wins();
7998549Sjkh	    break;
8008549Sjkh
80110882Speter	case 'A':
80210882Speter	    if (label_chunk_info[here].type != PART_SLICE) {
80315440Sjkh		msg = "You can only do this in a disk slice (at top of screen)";
80410882Speter		break;
80510882Speter	    }
80687557Sdillon	    /*
80787557Sdillon	     * Generate standard partitions automatically.  If we do not
80887557Sdillon	     * have sufficient space we attempt to scale-down the size
80987557Sdillon	     * of the partitions within certain bounds.
81087557Sdillon	     */
81187557Sdillon	    {
81287557Sdillon		int perc;
81387557Sdillon		int req = 0;
81412661Speter
81587557Sdillon		for (perc = 100; perc > 0; perc -= 5) {
81687557Sdillon		    req = 0;	/* reset for each loop */
81787557Sdillon		    if ((msg = try_auto_label(devs, dev, perc, &req)) == NULL)
81817362Sjkh			break;
81915440Sjkh		}
82087557Sdillon		if (msg) {
82187557Sdillon		    if (req) {
82287557Sdillon			msgConfirm(msg);
82318619Sjkh			clear_wins();
82487557Sdillon			msg = NULL;
82517362Sjkh		    }
82615440Sjkh		}
82710882Speter	    }
82815440Sjkh	    break;
82910882Speter
8308549Sjkh	case 'C':
8318549Sjkh	    if (label_chunk_info[here].type != PART_SLICE) {
8328549Sjkh		msg = "You can only do this in a master partition (see top of screen)";
8338549Sjkh		break;
8348549Sjkh	    }
8358549Sjkh	    sz = space_free(label_chunk_info[here].c);
8368669Sphk	    if (sz <= FS_MIN_SIZE) {
83712661Speter		msg = "Not enough space to create an additional FreeBSD partition";
8388669Sphk		break;
8398669Sphk	    }
84015440Sjkh	    else {
84118744Sjkh		char *val;
8428702Sjkh		int size;
8438702Sjkh		struct chunk *tmp;
8448820Sjkh		char osize[80];
8458702Sjkh		u_long flags = 0;
8468549Sjkh
8478820Sjkh		sprintf(osize, "%d", sz);
84818619Sjkh		val = msgGetInput(osize,
84957617Sjkh				  "Please specify the partition size in blocks or append a trailing G for\n"
85057617Sjkh				  "gigabytes, M for megabytes, or C for cylinders.\n"
85157617Sjkh				  "%d blocks (%dMB) are free.",
85218619Sjkh				  sz, sz / ONE_MEG);
85318619Sjkh		if (!val || (size = strtol(val, &cp, 0)) <= 0) {
85418619Sjkh		    clear_wins();
8558702Sjkh		    break;
85618619Sjkh		}
8578549Sjkh
8588751Sjkh		if (*cp) {
8598751Sjkh		    if (toupper(*cp) == 'M')
8608751Sjkh			size *= ONE_MEG;
86157617Sjkh		    else if (toupper(*cp) == 'G')
86257617Sjkh			size *= ONE_GIG;
8638751Sjkh		    else if (toupper(*cp) == 'C')
8648751Sjkh			size *= (label_chunk_info[here].c->disk->bios_hd * label_chunk_info[here].c->disk->bios_sect);
8658751Sjkh		}
8668820Sjkh		if (size <= FS_MIN_SIZE) {
8678820Sjkh		    msgConfirm("The minimum filesystem size is %dMB", FS_MIN_SIZE / ONE_MEG);
86818619Sjkh		    clear_wins();
8698820Sjkh		    break;
8708820Sjkh		}
8718702Sjkh		type = get_partition_type();
87218619Sjkh		if (type == PART_NONE) {
87318619Sjkh		    clear_wins();
87418619Sjkh		    beep();
8758669Sphk		    break;
87618619Sjkh		}
8778669Sphk
8788702Sjkh		if (type == PART_FILESYSTEM) {
87918619Sjkh		    if ((p = get_mountpoint(NULL)) == NULL) {
88018619Sjkh			clear_wins();
88118619Sjkh			beep();
8828702Sjkh			break;
88318619Sjkh		    }
8848702Sjkh		    else if (!strcmp(p->mountpoint, "/"))
8858702Sjkh			flags |= CHUNK_IS_ROOT;
8868702Sjkh		    else
8878702Sjkh			flags &= ~CHUNK_IS_ROOT;
88818619Sjkh		}
88918619Sjkh		else
8908702Sjkh		    p = NULL;
8918702Sjkh
89276237Sjkh		if ((flags & CHUNK_IS_ROOT) && (size < (ROOT_MIN_SIZE * ONE_MEG))) {
89376237Sjkh		    msgConfirm("Warning: This is smaller than the recommended size for a\n"
89476237Sjkh			       "root partition.  For a variety of reasons, root\n"
89576237Sjkh			       "partitions should usually be at least %dMB in size", ROOT_MIN_SIZE);
8968672Sjkh		}
8978751Sjkh		tmp = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
8988702Sjkh					label_chunk_info[here].c,
8998702Sjkh					size, part,
9008702Sjkh					(type == PART_SWAP) ? FS_SWAP : FS_BSDFFS,
9018702Sjkh					flags);
9028702Sjkh		if (!tmp) {
9038702Sjkh		    msgConfirm("Unable to create the partition. Too big?");
90418619Sjkh		    clear_wins();
9058672Sjkh		    break;
9068672Sjkh		}
90779678Sobrien
90879678Sobrien#ifdef __alpha__
90979678Sobrien		/*
91079680Sobrien		 * SRM requires that the root partition is at the
91179678Sobrien		 * begining of the disk and cannot boot otherwise.
91279678Sobrien		 * Warn Alpha users if they are about to shoot themselves in
91379678Sobrien		 * the foot in this way.
91479678Sobrien		 *
91579678Sobrien		 * Since partitions may not start precisely at offset 0 we
91679678Sobrien		 * check for a "close to 0" instead. :-(
91779678Sobrien		 */
91879678Sobrien		if ((flags & CHUNK_IS_ROOT) && (tmp->offset > 1024)) {
91979680Sobrien		    msgConfirm("Your root partition `a' does not seem to be the first\n"
92079680Sobrien			       "partition.  The Alpha's firmware can only boot from the\n"
92179680Sobrien			       "first partition.  So it is unlikely that your current\n"
92279680Sobrien			       "disk layout will be bootable boot after installation.\n"
92379678Sobrien			       "\n"
92479678Sobrien			       "Please allocate the root partition before allocating\n"
92579678Sobrien			       "any others.\n");
92679678Sobrien		}
92779678Sobrien#endif	/* alpha */
92879678Sobrien
9298702Sjkh		if (type != PART_SWAP) {
9308669Sphk		    /* This is needed to tell the newfs -u about the size */
93114793Sjoerg		    tmp->private_data = new_part(p->mountpoint, p->newfs, tmp->size);
9328669Sphk		    safe_free(p);
93315355Sjkh		}
93415355Sjkh		else
93514793Sjoerg		    tmp->private_data = p;
9368702Sjkh		tmp->private_free = safe_free;
93774156Sjkh		if (variable_cmp(DISK_LABELLED, "written"))
93843685Sjkh		    variable_set2(DISK_LABELLED, "yes", 0);
93930345Sjkh		record_label_chunks(devs, dev);
94018619Sjkh		clear_wins();
94179678Sobrien                /* This is where we assign focus to new label so it shows. */
94229249Sjkh                {
94329249Sjkh                    int i;
94429249Sjkh		    label_focus = -1;
94529249Sjkh                    for (i = 0; label_chunk_info[i].c; ++i) {
94629249Sjkh                    	if (label_chunk_info[i].c == tmp) {
94729249Sjkh			    label_focus = i;
94829249Sjkh			    break;
94929249Sjkh			}
95029249Sjkh		    }
95129249Sjkh		    if (label_focus == -1)
95229249Sjkh                    	label_focus = i - 1;
95329249Sjkh                }
9548549Sjkh	    }
9558549Sjkh	    break;
9568549Sjkh
95717397Sjkh	case KEY_DC:
95888996Sdillon	case 'R':	/* recover space (delete w/ recover) */
95988996Sdillon	    /*
96088996Sdillon	     * Delete the partition w/ space recovery.
96188996Sdillon	     */
96288996Sdillon	    rflags = DELCHUNK_RECOVER;
96388996Sdillon	    /* fall through */
9648549Sjkh	case 'D':	/* delete */
9658549Sjkh	    if (label_chunk_info[here].type == PART_SLICE) {
9668549Sjkh		msg = MSG_NOT_APPLICABLE;
9678549Sjkh		break;
9688549Sjkh	    }
9698549Sjkh	    else if (label_chunk_info[here].type == PART_FAT) {
9708705Sjkh		msg = "Use the Disk Partition Editor to delete DOS partitions";
9718549Sjkh		break;
9728549Sjkh	    }
97388996Sdillon	    Delete_Chunk2(label_chunk_info[here].c->disk, label_chunk_info[here].c, rflags);
97474156Sjkh	    if (variable_cmp(DISK_LABELLED, "written"))
97543685Sjkh		variable_set2(DISK_LABELLED, "yes", 0);
97630345Sjkh	    record_label_chunks(devs, dev);
9778549Sjkh	    break;
9788549Sjkh
9798549Sjkh	case 'M':	/* mount */
9808549Sjkh	    switch(label_chunk_info[here].type) {
9818549Sjkh	    case PART_SLICE:
9828549Sjkh		msg = MSG_NOT_APPLICABLE;
9838549Sjkh		break;
9848549Sjkh
9858549Sjkh	    case PART_SWAP:
9868549Sjkh		msg = "You don't need to specify a mountpoint for a swap partition.";
9878549Sjkh		break;
9888549Sjkh
9898556Sjkh	    case PART_FAT:
9908549Sjkh	    case PART_FILESYSTEM:
99114793Sjoerg		oldp = label_chunk_info[here].c->private_data;
9928589Sjkh		p = get_mountpoint(label_chunk_info[here].c);
9938549Sjkh		if (p) {
9949202Srgrimes		    if (!oldp)
9959202Srgrimes		    	p->newfs = FALSE;
9968722Sjkh		    if (label_chunk_info[here].type == PART_FAT
9978722Sjkh			&& (!strcmp(p->mountpoint, "/") || !strcmp(p->mountpoint, "/usr")
9988722Sjkh			    || !strcmp(p->mountpoint, "/var"))) {
9998722Sjkh			msgConfirm("%s is an invalid mount point for a DOS partition!", p->mountpoint);
10008722Sjkh			strcpy(p->mountpoint, "/bogus");
10018722Sjkh		    }
10028549Sjkh		}
100374156Sjkh		if (variable_cmp(DISK_LABELLED, "written"))
100443685Sjkh		    variable_set2(DISK_LABELLED, "yes", 0);
100530345Sjkh		record_label_chunks(devs, dev);
100618636Sjkh		clear_wins();
10078549Sjkh		break;
10088549Sjkh
10098549Sjkh	    default:
10108549Sjkh		msgFatal("Bogus partition under cursor???");
10118549Sjkh		break;
10128549Sjkh	    }
10138549Sjkh	    break;
10148549Sjkh
10158549Sjkh	case 'N':	/* Set newfs options */
101614793Sjoerg	    if (label_chunk_info[here].c->private_data &&
101714793Sjoerg		((PartInfo *)label_chunk_info[here].c->private_data)->newfs)
101814793Sjoerg		getNewfsCmd(label_chunk_info[here].c->private_data);
10198549Sjkh	    else
10208549Sjkh		msg = MSG_NOT_APPLICABLE;
102118636Sjkh	    clear_wins();
10228549Sjkh	    break;
10238549Sjkh
102474086Sjkh	case 'S':	/* Toggle soft updates flag */
102574086Sjkh	    if (label_chunk_info[here].type == PART_FILESYSTEM) {
102674086Sjkh		PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
102774086Sjkh		if (pi)
102874086Sjkh		    pi->soft = !pi->soft;
102974086Sjkh		else
103074086Sjkh		    msg = MSG_NOT_APPLICABLE;
103174086Sjkh	    }
103274156Sjkh	    else
103374156Sjkh		msg = MSG_NOT_APPLICABLE;
103474086Sjkh	    break;
103574086Sjkh
10368549Sjkh	case 'T':	/* Toggle newfs state */
10379202Srgrimes	    if (label_chunk_info[here].type == PART_FILESYSTEM) {
103823729Sjkh		PartInfo *pi = ((PartInfo *)label_chunk_info[here].c->private_data);
103987581Sdillon		if (!pi->newfs)
104087581Sdillon		    label_chunk_info[here].c->flags |= CHUNK_NEWFS;
104187581Sdillon		else
104287581Sdillon		    label_chunk_info[here].c->flags &= ~CHUNK_NEWFS;
104387581Sdillon
104423729Sjkh		label_chunk_info[here].c->private_data =
104523729Sjkh		    new_part(pi ? pi->mountpoint : NULL, pi ? !pi->newfs : TRUE, label_chunk_info[here].c->size);
104674156Sjkh		if (pi && pi->soft)
104774156Sjkh		    ((PartInfo *)label_chunk_info[here].c->private_data)->soft = 1;
104823729Sjkh		safe_free(pi);
104923729Sjkh		label_chunk_info[here].c->private_free = safe_free;
105074156Sjkh		if (variable_cmp(DISK_LABELLED, "written"))
105143685Sjkh		    variable_set2(DISK_LABELLED, "yes", 0);
105218619Sjkh	    }
10538549Sjkh	    else
10548549Sjkh		msg = MSG_NOT_APPLICABLE;
10558549Sjkh	    break;
10568549Sjkh
10578820Sjkh	case 'U':
105812661Speter	    clear();
105974156Sjkh	    if (!variable_cmp(DISK_LABELLED, "written")) {
106018744Sjkh		msgConfirm("You've already written out your changes -\n"
106118744Sjkh			   "it's too late to undo!");
106218744Sjkh	    }
106370005Sjkh	    else if (!msgNoYes("Are you SURE you want to Undo everything?")) {
106418744Sjkh		variable_unset(DISK_PARTITIONED);
106518744Sjkh		variable_unset(DISK_LABELLED);
106618744Sjkh		for (i = 0; devs[i]; i++) {
106718744Sjkh		    Disk *d;
106812661Speter
106918744Sjkh		    if (!devs[i]->enabled)
107018744Sjkh			continue;
107118744Sjkh		    else if ((d = Open_Disk(devs[i]->name)) != NULL) {
107218744Sjkh			Free_Disk(devs[i]->private);
107318744Sjkh			devs[i]->private = d;
107430345Sjkh			diskPartition(devs[i]);
107518744Sjkh		    }
10768824Sjkh		}
107730345Sjkh		record_label_chunks(devs, dev);
10788824Sjkh	    }
107918636Sjkh	    clear_wins();
10808824Sjkh	    break;
10818820Sjkh
10828549Sjkh	case 'W':
108374156Sjkh	    if (!variable_cmp(DISK_LABELLED, "written")) {
108418744Sjkh		msgConfirm("You've already written out your changes - if you\n"
108574156Sjkh			   "wish to overwrite them, you'll have to restart\n"
108674156Sjkh			   "sysinstall first.");
108718744Sjkh	    }
108870005Sjkh	    else if (!msgNoYes("WARNING:  This should only be used when modifying an EXISTING\n"
108918687Sjkh			  "installation.  If you are installing FreeBSD for the first time\n"
109018687Sjkh			  "then you should simply type Q when you're finished here and your\n"
109118687Sjkh			  "changes will be committed in one batch automatically at the end of\n"
109218687Sjkh			  "these questions.\n\n"
109318687Sjkh			  "Are you absolutely sure you want to do this now?")) {
109443685Sjkh		variable_set2(DISK_LABELLED, "yes", 0);
109512661Speter		diskLabelCommit(NULL);
109612661Speter	    }
109718636Sjkh	    clear_wins();
109810882Speter	    break;
109910882Speter
110010882Speter	case '|':
110170005Sjkh	    if (!msgNoYes("Are you sure you want to go into Wizard mode?\n\n"
110212661Speter			  "This is an entirely undocumented feature which you are not\n"
110312661Speter			  "expected to understand!")) {
11048549Sjkh		int i;
11058549Sjkh		Device **devs;
11068549Sjkh
11078549Sjkh		dialog_clear();
11088549Sjkh		end_dialog();
11098549Sjkh		DialogActive = FALSE;
11108549Sjkh		devs = deviceFind(NULL, DEVICE_TYPE_DISK);
11118549Sjkh		if (!devs) {
111212661Speter		    msgConfirm("Can't find any disk devices!");
11138549Sjkh		    break;
11148549Sjkh		}
11158668Sphk		for (i = 0; devs[i] && ((Disk *)devs[i]->private); i++) {
11168613Sjkh		    if (devs[i]->enabled)
11178613Sjkh		    	slice_wizard(((Disk *)devs[i]->private));
11188613Sjkh		}
111974156Sjkh		if (variable_cmp(DISK_LABELLED, "written"))
112043685Sjkh		    variable_set2(DISK_LABELLED, "yes", 0);
11218665Sphk		DialogActive = TRUE;
112230345Sjkh		record_label_chunks(devs, dev);
112318636Sjkh		clear_wins();
11248549Sjkh	    }
11258549Sjkh	    else
11268549Sjkh		msg = "A most prudent choice!";
11278549Sjkh	    break;
11288549Sjkh
112921698Sjkh	case '\033':	/* ESC */
11309202Srgrimes	case 'Q':
11318549Sjkh	    labeling = FALSE;
11328549Sjkh	    break;
11338549Sjkh
11348549Sjkh	default:
11358549Sjkh	    beep();
113617362Sjkh	    sprintf(_msg, "Invalid key %d - Type F1 or ? for help", key);
113717362Sjkh	    msg = _msg;
11388549Sjkh	    break;
11398549Sjkh	}
114029633Sjkh        if (label_chunk_info[here].type == PART_SLICE)
114129633Sjkh            pslice_focus = here;
114229633Sjkh        else
114329633Sjkh            label_focus = here;
11448549Sjkh    }
114554587Sjkh    restorescr(w);
114654587Sjkh    return DITEM_SUCCESS;
11478549Sjkh}
114826456Sjkh
114987557Sdillonstatic __inline int
115087557Sdillonrequested_part_size(char *varName, int nom, int def, int perc)
115187557Sdillon{
115287557Sdillon    char *cp;
115387557Sdillon    int sz;
115487557Sdillon
115587557Sdillon    if ((cp = variable_get(VAR_ROOT_SIZE)) != NULL)
115687557Sdillon	sz = atoi(cp);
115787557Sdillon    else
115887557Sdillon	sz = nom + (def - nom) * perc / 100;
115987557Sdillon    return(sz * ONE_MEG);
116087557Sdillon}
116187557Sdillon
116287557Sdillon/*
116387557Sdillon * Attempt to auto-label the disk.  'perc' (0-100) scales
116487557Sdillon * the size of the various partitions within appropriate
116587557Sdillon * bounds (NOMINAL through DEFAULT sizes).  The procedure
116687557Sdillon * succeeds of NULL is returned.  A non-null return message
116787557Sdillon * is either a failure-status message (*req == 0), or
116887557Sdillon * a confirmation requestor (*req == 1).  *req is 0 on
116987557Sdillon * entry to this call.
117087557Sdillon *
117187583Sdillon * We autolabel the following partitions:  /, swap, /var, /tmp, /usr,
117287557Sdillon * and /home.  /home receives any extra left over disk space.
117387557Sdillon */
117487557Sdillonstatic char *
117587557Sdillontry_auto_label(Device **devs, Device *dev, int perc, int *req)
117687557Sdillon{
117787557Sdillon    int sz;
117887557Sdillon    struct chunk *root_chunk = NULL;
117987557Sdillon    struct chunk *swap_chunk = NULL;
118087557Sdillon    struct chunk *usr_chunk = NULL;
118187557Sdillon    struct chunk *var_chunk = NULL;
118287581Sdillon    struct chunk *tmp_chunk = NULL;
118387557Sdillon    struct chunk *home_chunk = NULL;
118487557Sdillon    int mib[2];
118587557Sdillon    unsigned int physmem;
118687557Sdillon    size_t size;
118787557Sdillon    Chunk *rootdev, *swapdev, *usrdev, *vardev;
118887581Sdillon    Chunk *tmpdev, *homedev;
118987557Sdillon    char *msg = NULL;
119087557Sdillon
119187557Sdillon    sz = space_free(label_chunk_info[here].c);
119287557Sdillon    if (sz <= FS_MIN_SIZE)
119387557Sdillon	return("Not enough free space to create a new partition in the slice");
119487557Sdillon
119587557Sdillon    (void)checkLabels(FALSE, &rootdev, &swapdev, &usrdev,
119687581Sdillon			&vardev, &tmpdev, &homedev);
119787557Sdillon    if (!rootdev) {
119887557Sdillon	sz = requested_part_size(VAR_ROOT_SIZE, ROOT_NOMINAL_SIZE, ROOT_DEFAULT_SIZE, perc);
119987557Sdillon
120087581Sdillon	root_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
120187581Sdillon			    label_chunk_info[here].c, sz, part,
120287581Sdillon			    FS_BSDFFS,  CHUNK_IS_ROOT | CHUNK_AUTO_SIZE);
120387557Sdillon	if (!root_chunk) {
120487557Sdillon	    *req = 1;
120587557Sdillon	    msg = "Unable to create the root partition. Too big?";
120687557Sdillon	    goto done;
120787557Sdillon	}
120887557Sdillon	root_chunk->private_data = new_part("/", TRUE, root_chunk->size);
120987557Sdillon	root_chunk->private_free = safe_free;
121087581Sdillon	root_chunk->flags |= CHUNK_NEWFS;
121187557Sdillon	record_label_chunks(devs, dev);
121287557Sdillon    }
121387557Sdillon    if (!swapdev) {
121487557Sdillon	sz = requested_part_size(VAR_SWAP_SIZE, 0, 0, perc);
121587557Sdillon	if (sz == 0) {
121687557Sdillon	    int nom;
121787557Sdillon	    int def;
121887557Sdillon
121987557Sdillon	    mib[0] = CTL_HW;
122087557Sdillon	    mib[1] = HW_PHYSMEM;
122187557Sdillon	    size = sizeof physmem;
122287557Sdillon	    sysctl(mib, 2, &physmem, &size, (void *)0, (size_t)0);
122387557Sdillon	    def = 2 * (int)(physmem / 512);
122487557Sdillon	    if (def < SWAP_MIN_SIZE * ONE_MEG)
122587557Sdillon		def = SWAP_MIN_SIZE * ONE_MEG;
122687557Sdillon	    if (def > SWAP_AUTO_LIMIT_SIZE * ONE_MEG)
122787557Sdillon		def = SWAP_AUTO_LIMIT_SIZE * ONE_MEG;
122887557Sdillon	    nom = (int)(physmem / 512) / 2;
122987557Sdillon	    sz = nom + (def - nom) * perc / 100;
123087557Sdillon	}
123187581Sdillon	swap_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
123287581Sdillon			    label_chunk_info[here].c, sz, part,
123387581Sdillon			    FS_SWAP, CHUNK_AUTO_SIZE);
123487557Sdillon	if (!swap_chunk) {
123587557Sdillon	    *req = 1;
123687557Sdillon	    msg = "Unable to create the swap partition. Too big?";
123787557Sdillon	    goto done;
123887557Sdillon	}
123987557Sdillon	swap_chunk->private_data = 0;
124087557Sdillon	swap_chunk->private_free = safe_free;
124187557Sdillon	record_label_chunks(devs, dev);
124287557Sdillon    }
124387557Sdillon    if (!vardev) {
124487557Sdillon	sz = requested_part_size(VAR_VAR_SIZE, VAR_NOMINAL_SIZE, VAR_DEFAULT_SIZE, perc);
124587557Sdillon
124687581Sdillon	var_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
124787581Sdillon				label_chunk_info[here].c, sz, part,
124887581Sdillon				FS_BSDFFS, CHUNK_AUTO_SIZE);
124987557Sdillon	if (!var_chunk) {
125087557Sdillon	    *req = 1;
125187557Sdillon	    msg = "Not enough free space for /var - you will need to\n"
125287557Sdillon		   "partition your disk manually with a custom install!";
125387557Sdillon	    goto done;
125487557Sdillon	}
125587557Sdillon	var_chunk->private_data = new_part("/var", TRUE, var_chunk->size);
125687557Sdillon	var_chunk->private_free = safe_free;
125787581Sdillon	var_chunk->flags |= CHUNK_NEWFS;
125887557Sdillon	record_label_chunks(devs, dev);
125987557Sdillon    }
126087583Sdillon    if (!tmpdev && !variable_get(VAR_NO_TMP)) {
126187583Sdillon	sz = requested_part_size(VAR_TMP_SIZE, TMP_NOMINAL_SIZE, TMP_DEFAULT_SIZE, perc);
126287557Sdillon
126387581Sdillon	tmp_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
126487581Sdillon				label_chunk_info[here].c, sz, part,
126587581Sdillon				FS_BSDFFS, CHUNK_AUTO_SIZE);
126687581Sdillon	if (!tmp_chunk) {
126787557Sdillon	    *req = 1;
126887583Sdillon	    msg = "Not enough free space for /tmp - you will need to\n"
126987557Sdillon		   "partition your disk manually with a custom install!";
127087557Sdillon	    goto done;
127187557Sdillon	}
127287581Sdillon	tmp_chunk->private_data = new_part("/tmp", TRUE, tmp_chunk->size);
127387581Sdillon	tmp_chunk->private_free = safe_free;
127487581Sdillon	tmp_chunk->flags |= CHUNK_NEWFS;
127587557Sdillon	record_label_chunks(devs, dev);
127687557Sdillon    }
127787557Sdillon    if (!usrdev && !variable_get(VAR_NO_USR)) {
127887557Sdillon	sz = requested_part_size(VAR_USR_SIZE, USR_NOMINAL_SIZE, USR_DEFAULT_SIZE, perc);
127988996Sdillon#if AUTO_HOME == 0
128087557Sdillon	    sz = space_free(label_chunk_info[here].c);
128187557Sdillon#endif
128287557Sdillon	if (sz) {
128387557Sdillon	    if (sz < (USR_MIN_SIZE * ONE_MEG)) {
128487557Sdillon		*req = 1;
128587557Sdillon		msg = "Not enough free space for /usr - you will need to\n"
128687557Sdillon		       "partition your disk manually with a custom install!";
128787557Sdillon	    }
128887557Sdillon
128987557Sdillon	    usr_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
129087581Sdillon				    label_chunk_info[here].c, sz, part,
129187581Sdillon				    FS_BSDFFS, CHUNK_AUTO_SIZE);
129287557Sdillon	    if (!usr_chunk) {
129387557Sdillon		msg = "Unable to create the /usr partition.  Not enough space?\n"
129487557Sdillon			   "You will need to partition your disk manually with a custom install!";
129587557Sdillon		goto done;
129687557Sdillon	    }
129787557Sdillon	    usr_chunk->private_data = new_part("/usr", TRUE, usr_chunk->size);
129887557Sdillon	    usr_chunk->private_free = safe_free;
129987581Sdillon	    usr_chunk->flags |= CHUNK_NEWFS;
130087557Sdillon	    record_label_chunks(devs, dev);
130187557Sdillon	}
130287557Sdillon    }
130388996Sdillon#if AUTO_HOME == 1
130487557Sdillon    if (!homedev && !variable_get(VAR_NO_HOME)) {
130587557Sdillon	sz = requested_part_size(VAR_HOME_SIZE, HOME_NOMINAL_SIZE, HOME_DEFAULT_SIZE, perc);
130687557Sdillon	if (sz < space_free(label_chunk_info[here].c))
130787557Sdillon	    sz = space_free(label_chunk_info[here].c);
130887557Sdillon	if (sz) {
130987557Sdillon	    if (sz < (HOME_MIN_SIZE * ONE_MEG)) {
131087557Sdillon		*req = 1;
131187557Sdillon		msg = "Not enough free space for /home - you will need to\n"
131287557Sdillon		       "partition your disk manually with a custom install!";
131387557Sdillon		goto done;
131487557Sdillon	    }
131587557Sdillon
131687557Sdillon	    home_chunk = Create_Chunk_DWIM(label_chunk_info[here].c->disk,
131787581Sdillon				    label_chunk_info[here].c, sz, part,
131887581Sdillon				    FS_BSDFFS, CHUNK_AUTO_SIZE);
131987557Sdillon	    if (!home_chunk) {
132087557Sdillon		msg = "Unable to create the /home partition.  Not enough space?\n"
132187557Sdillon			   "You will need to partition your disk manually with a custom install!";
132287557Sdillon		goto done;
132387557Sdillon	    }
132487557Sdillon	    home_chunk->private_data = new_part("/home", TRUE, home_chunk->size);
132587557Sdillon	    home_chunk->private_free = safe_free;
132687581Sdillon	    home_chunk->flags |= CHUNK_NEWFS;
132787557Sdillon	    record_label_chunks(devs, dev);
132887557Sdillon	}
132987557Sdillon    }
133088996Sdillon#endif
133187557Sdillon
133287557Sdillon    /* At this point, we're reasonably "labelled" */
133387557Sdillon    if (variable_cmp(DISK_LABELLED, "written"))
133487557Sdillon	variable_set2(DISK_LABELLED, "yes", 0);
133587557Sdillon
133687557Sdillondone:
133787557Sdillon    if (msg) {
133887557Sdillon	if (root_chunk)
133987557Sdillon	    Delete_Chunk(root_chunk->disk, root_chunk);
134087557Sdillon	if (swap_chunk)
134187557Sdillon	    Delete_Chunk(swap_chunk->disk, swap_chunk);
134287557Sdillon	if (var_chunk)
134387557Sdillon	    Delete_Chunk(var_chunk->disk, var_chunk);
134487581Sdillon	if (tmp_chunk)
134587581Sdillon	    Delete_Chunk(tmp_chunk->disk, tmp_chunk);
134687557Sdillon	if (usr_chunk)
134787557Sdillon	    Delete_Chunk(usr_chunk->disk, usr_chunk);
134887557Sdillon	if (home_chunk)
134987557Sdillon	    Delete_Chunk(home_chunk->disk, home_chunk);
135087557Sdillon	record_label_chunks(devs, dev);
135187557Sdillon    }
135287557Sdillon    return(msg);
135387557Sdillon}
135487557Sdillon
135526456Sjkhstatic int
135630345SjkhdiskLabelNonInteractive(Device *dev)
135726456Sjkh{
135826456Sjkh    char *cp;
135926456Sjkh    PartType type;
136026456Sjkh    PartInfo *p;
136126456Sjkh    u_long flags = 0;
136226456Sjkh    int i, status;
136326456Sjkh    Device **devs;
136426456Sjkh    Disk *d;
136554587Sjkh
136626456Sjkh    status = DITEM_SUCCESS;
136726456Sjkh    cp = variable_get(VAR_DISK);
136826456Sjkh    if (!cp) {
136926456Sjkh	msgConfirm("diskLabel:  No disk selected - can't label automatically.");
137026456Sjkh	return DITEM_FAILURE;
137126456Sjkh    }
137226456Sjkh    devs = deviceFind(cp, DEVICE_TYPE_DISK);
137326456Sjkh    if (!devs) {
137426456Sjkh	msgConfirm("diskLabel: No disk device %s found!", cp);
137526456Sjkh	return DITEM_FAILURE;
137626456Sjkh    }
137730345Sjkh    if (dev)
137830345Sjkh	d = dev->private;
137930345Sjkh    else
138030345Sjkh	d = devs[0]->private;
138142386Sjkh#ifdef __alpha__
138243392Sjkh    maybe_dedicate(d);
138342386Sjkh#endif
138430345Sjkh    record_label_chunks(devs, dev);
138526456Sjkh    for (i = 0; label_chunk_info[i].c; i++) {
138626456Sjkh	Chunk *c1 = label_chunk_info[i].c;
138726456Sjkh
138826456Sjkh	if (label_chunk_info[i].type == PART_SLICE) {
138928075Sjkh	    char name[512];
139074674Sjkh	    int entries = 1;
139126456Sjkh
139228075Sjkh	    while (entries) {
139328075Sjkh		snprintf(name, sizeof name, "%s-%d", c1->name, entries);
139428075Sjkh		if ((cp = variable_get(name)) != NULL) {
139574674Sjkh		    int sz, soft = 0;
139628075Sjkh		    char typ[10], mpoint[50];
139726456Sjkh
139874156Sjkh		    if (sscanf(cp, "%s %d %s %d", typ, &sz, mpoint, &soft) < 3) {
139928075Sjkh			msgConfirm("For slice entry %s, got an invalid detail entry of: %s",  c1->name, cp);
140026456Sjkh			status = DITEM_FAILURE;
140126456Sjkh			continue;
140226456Sjkh		    }
140326456Sjkh		    else {
140428075Sjkh			Chunk *tmp;
140528075Sjkh
140628075Sjkh			if (!strcmp(typ, "swap")) {
140728075Sjkh			    type = PART_SWAP;
140828075Sjkh			    strcpy(mpoint, "SWAP");
140928075Sjkh			}
141028075Sjkh			else {
141128075Sjkh			    type = PART_FILESYSTEM;
141228075Sjkh			    if (!strcmp(mpoint, "/"))
141328075Sjkh				flags |= CHUNK_IS_ROOT;
141433132Sjkh			    else
141533132Sjkh				flags &= ~CHUNK_IS_ROOT;
141628075Sjkh			}
141728075Sjkh			if (!sz)
141828075Sjkh			    sz = space_free(c1);
141928075Sjkh			if (sz > space_free(c1)) {
142028075Sjkh			    msgConfirm("Not enough free space to create partition: %s", mpoint);
142128075Sjkh			    status = DITEM_FAILURE;
142228075Sjkh			    continue;
142328075Sjkh			}
142428075Sjkh			if (!(tmp = Create_Chunk_DWIM(d, c1, sz, part,
142528075Sjkh						      (type == PART_SWAP) ? FS_SWAP : FS_BSDFFS, flags))) {
142628075Sjkh			    msgConfirm("Unable to create from partition spec: %s. Too big?", cp);
142728075Sjkh			    status = DITEM_FAILURE;
142828075Sjkh			    break;
142928075Sjkh			}
143028075Sjkh			else {
143128075Sjkh			    tmp->private_data = new_part(mpoint, TRUE, sz);
143228075Sjkh			    tmp->private_free = safe_free;
143374674Sjkh			    ((PartInfo *)tmp->private_data)->soft = soft;
143428075Sjkh			    status = DITEM_SUCCESS;
143528075Sjkh			}
143626456Sjkh		    }
143728075Sjkh		    entries++;
143826456Sjkh		}
143928075Sjkh		else {
144028075Sjkh		    /* No more matches, leave the loop */
144128075Sjkh		    entries = 0;
144228075Sjkh		}
144326456Sjkh	    }
144426456Sjkh	}
144526456Sjkh	else {
144628075Sjkh	    /* Must be something we can set a mountpoint for */
144726456Sjkh	    cp = variable_get(c1->name);
144826456Sjkh	    if (cp) {
144928075Sjkh		char mpoint[50], do_newfs[8];
145026456Sjkh		Boolean newfs = FALSE;
145126456Sjkh
145228075Sjkh		do_newfs[0] = '\0';
145328075Sjkh		if (sscanf(cp, "%s %s", mpoint, do_newfs) != 2) {
145426456Sjkh		    msgConfirm("For slice entry %s, got an invalid detail entry of: %s", c1->name, cp);
145526456Sjkh		    status = DITEM_FAILURE;
145626456Sjkh		    continue;
145726456Sjkh		}
145828075Sjkh		newfs = toupper(do_newfs[0]) == 'Y' ? TRUE : FALSE;
145926456Sjkh		if (c1->private_data) {
146026456Sjkh		    p = c1->private_data;
146126456Sjkh		    p->newfs = newfs;
146226456Sjkh		    strcpy(p->mountpoint, mpoint);
146326456Sjkh		}
146426456Sjkh		else {
146526456Sjkh		    c1->private_data = new_part(mpoint, newfs, 0);
146626456Sjkh		    c1->private_free = safe_free;
146726456Sjkh		}
146826456Sjkh		if (!strcmp(mpoint, "/"))
146926456Sjkh		    c1->flags |= CHUNK_IS_ROOT;
147026456Sjkh		else
147126456Sjkh		    c1->flags &= ~CHUNK_IS_ROOT;
147226456Sjkh	    }
147326456Sjkh	}
147426456Sjkh    }
147526456Sjkh    if (status == DITEM_SUCCESS)
147643685Sjkh	variable_set2(DISK_LABELLED, "yes", 0);
147726456Sjkh    return status;
147826456Sjkh}
1479