disks.c revision 8408
1297627Sjmcneill/*
2297627Sjmcneill * The new sysinstall program.
3297627Sjmcneill *
4297627Sjmcneill * This is probably the last program in the `sysinstall' line - the next
5297627Sjmcneill * generation being essentially a complete rewrite.
6297627Sjmcneill *
7297627Sjmcneill * $Id: disks.c,v 1.14 1995/05/10 08:03:21 jkh Exp $
8297627Sjmcneill *
9297627Sjmcneill * Copyright (c) 1995
10297627Sjmcneill *	Jordan Hubbard.  All rights reserved.
11297627Sjmcneill *
12297627Sjmcneill * Redistribution and use in source and binary forms, with or without
13297627Sjmcneill * modification, are permitted provided that the following conditions
14297627Sjmcneill * are met:
15297627Sjmcneill * 1. Redistributions of source code must retain the above copyright
16297627Sjmcneill *    notice, this list of conditions and the following disclaimer,
17297627Sjmcneill *    verbatim and that no modifications are made prior to this
18297627Sjmcneill *    point in the file.
19297627Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
20297627Sjmcneill *    notice, this list of conditions and the following disclaimer in the
21297627Sjmcneill *    documentation and/or other materials provided with the distribution.
22297627Sjmcneill * 3. All advertising materials mentioning features or use of this software
23297627Sjmcneill *    must display the following acknowledgement:
24297627Sjmcneill *	This product includes software developed by Jordan Hubbard
25297627Sjmcneill *	for the FreeBSD Project.
26297627Sjmcneill * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
27297627Sjmcneill *    endorse or promote products derived from this software without specific
28297627Sjmcneill *    prior written permission.
29297627Sjmcneill *
30297627Sjmcneill * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
31297627Sjmcneill * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32297627Sjmcneill * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33297627Sjmcneill * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
34297627Sjmcneill * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35297627Sjmcneill * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36297627Sjmcneill * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
37297627Sjmcneill * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38297627Sjmcneill * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39297627Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40297627Sjmcneill * SUCH DAMAGE.
41297627Sjmcneill *
42297627Sjmcneill */
43297627Sjmcneill
44297627Sjmcneill#include "sysinstall.h"
45297627Sjmcneill#include <ctype.h>
46297627Sjmcneill#include <sys/disklabel.h>
47297627Sjmcneill
48297627Sjmcneill/*
49297627Sjmcneill * I make some pretty gross assumptions about having a max of 50 chunks
50297627Sjmcneill * total - 8 slices and 42 partitions.  I can't easily display many more
51297627Sjmcneill * than that on the screen at once!
52308274Smanu *
53305436Smanu * For 2.1 I'll revisit this and try to make it more dynamic, but since
54297627Sjmcneill * this will catch 99.99% of all possible cases, I'm not too worried.
55297627Sjmcneill */
56297627Sjmcneill
57297627Sjmcneill#define MAX_CHUNKS	50
58297627Sjmcneill
59297627Sjmcneill/* Where to start printing the freebsd slices */
60297627Sjmcneill#define CHUNK_SLICE_START_ROW		2
61297627Sjmcneill#define CHUNK_PART_START_ROW		10
62297627Sjmcneill
63297627Sjmcneill/* The smallest filesystem we're willing to create */
64297627Sjmcneill#define FS_MIN_SIZE			2048
65297627Sjmcneill
66297627Sjmcneill#define MSG_NOT_APPLICABLE		"That option is not applicable here"
67297627Sjmcneill
68297627Sjmcneillstatic struct {
69297627Sjmcneill    struct disk *d;
70297627Sjmcneill    struct chunk *c;
71297627Sjmcneill    PartType type;
72297627Sjmcneill} fbsd_chunk_info[MAX_CHUNKS + 1];
73297627Sjmcneillstatic int current_chunk;
74297627Sjmcneill
75297627Sjmcneill
76297627Sjmcneillstatic Boolean
77297627Sjmcneillcheck_conflict(char *name)
78297627Sjmcneill{
79297627Sjmcneill    int i;
80297627Sjmcneill
81297627Sjmcneill    for (i = 0; fbsd_chunk_info[i].d; i++)
82297627Sjmcneill	if (fbsd_chunk_info[i].type == PART_FILESYSTEM &&
83297627Sjmcneill	    fbsd_chunk_info[i].c->private &&
84297627Sjmcneill	    !strcmp(((PartInfo *)fbsd_chunk_info[i].c->private)->mountpoint,
85297627Sjmcneill		    name))
86297627Sjmcneill	    return TRUE;
87297627Sjmcneill    return FALSE;
88297627Sjmcneill}
89297627Sjmcneill
90297627Sjmcneillstatic int
91297627Sjmcneillspace_free(struct chunk *c)
92297627Sjmcneill{
93297627Sjmcneill    struct chunk *c1 = c->part;
94297627Sjmcneill    int sz = c->size;
95297627Sjmcneill
96297627Sjmcneill    while (c1) {
97297627Sjmcneill	if (c1->type != unused)
98297627Sjmcneill	    sz -= c1->size;
99297627Sjmcneill	c1 = c1->next;
100297627Sjmcneill    }
101297627Sjmcneill    if (sz < 0)
102297627Sjmcneill	msgFatal("Partitions are larger than actual chunk??");
103297627Sjmcneill    return sz;
104297627Sjmcneill}
105297627Sjmcneill
106305436Smanustatic void
107305436Smanurecord_fbsd_chunks()
108305436Smanu{
109305436Smanu    int i, j, p;
110305436Smanu    struct chunk *c1, *c2;
111305436Smanu
112305436Smanu    j = p = 0;
113299688Smanu    for (i = 0; Disks[i]; i++) {
114299688Smanu	if (!Disks[i]->chunks)
115299688Smanu	    msgFatal("No chunk list found for %s!", Disks[i]->name);
116299688Smanu
117299688Smanu	/* Put the freebsd chunks first */
118299688Smanu	for (c1 = Disks[i]->chunks->part; c1; c1 = c1->next) {
119299688Smanu	    if (c1->type == freebsd) {
120299688Smanu		fbsd_chunk_info[j].type = PART_SLICE;
121299688Smanu		fbsd_chunk_info[j].d = Disks[i];
122297627Sjmcneill		fbsd_chunk_info[j].c = c1;
123297627Sjmcneill		++j;
124297627Sjmcneill	    }
125297627Sjmcneill	}
126297627Sjmcneill    }
127297627Sjmcneill    for (i = 0; Disks[i]; i++) {
128297627Sjmcneill	/* Then buzz through and pick up the partitions */
129297627Sjmcneill	for (c1 = Disks[i]->chunks->part; c1; c1 = c1->next) {
130297627Sjmcneill	    if (c1->type == freebsd) {
131297627Sjmcneill		for (c2 = c1->part; c2; c2 = c2->next) {
132297627Sjmcneill		    if (c2->type == part) {
133297627Sjmcneill			if (c2->subtype == FS_SWAP)
134297627Sjmcneill			    fbsd_chunk_info[j].type = PART_SWAP;
135297627Sjmcneill			else
136297627Sjmcneill			    fbsd_chunk_info[j].type = PART_FILESYSTEM;
137297627Sjmcneill			fbsd_chunk_info[j].d = Disks[i];
138297627Sjmcneill			fbsd_chunk_info[j].c = c2;
139297627Sjmcneill			++j;
140297627Sjmcneill		    }
141297627Sjmcneill		}
142297627Sjmcneill	    }
143297627Sjmcneill	}
144297627Sjmcneill    }
145299113Sjmcneill    fbsd_chunk_info[j].d = NULL;
146299113Sjmcneill    fbsd_chunk_info[j].c = NULL;
147299113Sjmcneill    if (current_chunk >= j)
148299113Sjmcneill	current_chunk = j  ? j - 1 : 0;
149299113Sjmcneill}
150299113Sjmcneill
151297627Sjmcneillstatic PartInfo *
152297627Sjmcneillnew_part(char *mpoint, Boolean newfs)
153297627Sjmcneill{
154297627Sjmcneill    PartInfo *ret;
155297627Sjmcneill
156297627Sjmcneill    ret = (PartInfo *)safe_malloc(sizeof(PartInfo));
157297627Sjmcneill    strncpy(ret->mountpoint, mpoint, FILENAME_MAX);
158297627Sjmcneill    strcpy(ret->newfs_cmd, "newfs");
159297627Sjmcneill    ret->newfs = newfs;
160297627Sjmcneill    return ret;
161297627Sjmcneill}
162297627Sjmcneill
163297627SjmcneillPartInfo *
164297627Sjmcneillget_mountpoint(struct chunk *c)
165297627Sjmcneill{
166297627Sjmcneill    char *val;
167297627Sjmcneill    PartInfo *tmp;
168297627Sjmcneill
169297627Sjmcneill    val = msgGetInput(c && c->private ?
170297627Sjmcneill		      ((PartInfo *)c->private)->mountpoint : NULL,
171305436Smanu		      "Please specify a mount point for the partition");
172299688Smanu    if (val) {
173297627Sjmcneill	if (check_conflict(val)) {
174297627Sjmcneill	    msgConfirm("You already have a mount point for %s assigned!", val);
175299113Sjmcneill	    return NULL;
176297627Sjmcneill	}
177297627Sjmcneill	else if (*val != '/') {
178297627Sjmcneill	    msgConfirm("Mount point must start with a / character");
179297627Sjmcneill	    return NULL;
180297627Sjmcneill	}
181297627Sjmcneill	else if (!strcmp(val, "/")) {
182297627Sjmcneill	    if (c && c->flags & CHUNK_PAST_1024) {
183297627SjmcneillmsgConfirm("This region cannot be used for your root partition as\nit is past the 1024'th cylinder mark and the system would not be\nable to boot from it.  Please pick another location for your\nroot partition and try again!");
184297627Sjmcneill		return NULL;
185297627Sjmcneill	    }
186297627Sjmcneill	    else if (c)
187297627Sjmcneill		c->flags |= CHUNK_IS_ROOT;
188297627Sjmcneill	}
189297627Sjmcneill	else if (c)
190297627Sjmcneill	    c->flags &= ~CHUNK_IS_ROOT;
191297627Sjmcneill	safe_free(c ? c->private : NULL);
192297627Sjmcneill	tmp = new_part(val, TRUE);
193297627Sjmcneill	if (c) {
194297627Sjmcneill	    c->private = tmp;
195297627Sjmcneill	    c->private_free = safe_free;
196297627Sjmcneill	}
197297627Sjmcneill	return tmp;
198297627Sjmcneill    }
199297627Sjmcneill    return NULL;
200297627Sjmcneill}
201297627Sjmcneill
202297627Sjmcneillstatic PartType
203297627Sjmcneillget_partition_type(void)
204297627Sjmcneill{
205297627Sjmcneill    char selection[20];
206297627Sjmcneill    static unsigned char *fs_types[] = {
207297627Sjmcneill	"FS",
208297627Sjmcneill	"A file system",
209297627Sjmcneill	"Swap",
210297627Sjmcneill	"A swap partition.",
211297627Sjmcneill    };
212297627Sjmcneill
213297627Sjmcneill    if (!dialog_menu("Please choose a partition type",
214297627Sjmcneill		    "If you want to use this partition for swap space, select Swap.\nIf you want to put a filesystem on it, choose FS.", -1, -1, 2, 2, fs_types, selection, NULL, NULL)) {
215297627Sjmcneill	if (!strcmp(selection, "FS"))
216297627Sjmcneill	    return PART_FILESYSTEM;
217297627Sjmcneill	else if (!strcmp(selection, "Swap"))
218297627Sjmcneill	    return PART_SWAP;
219297627Sjmcneill    }
220297627Sjmcneill    return PART_NONE;
221297627Sjmcneill}
222297627Sjmcneill
223297627Sjmcneillstatic void
224297627SjmcneillgetNewfsCmd(PartInfo *p)
225297627Sjmcneill{
226297627Sjmcneill    char *val;
227297627Sjmcneill
228297627Sjmcneill    val = msgGetInput(p->newfs_cmd,
229297627Sjmcneill		      "Please enter the newfs command and options you'd like to use in\ncreating this file system.");
230297627Sjmcneill    if (val)
231297627Sjmcneill	strncpy(p->newfs_cmd, val, NEWFS_CMD_MAX);
232297627Sjmcneill}
233297627Sjmcneill
234297627Sjmcneill
235297627Sjmcneill#define MAX_MOUNT_NAME	12
236297627Sjmcneill
237297627Sjmcneill#define PART_PART_COL	0
238297627Sjmcneill#define PART_MOUNT_COL	8
239297627Sjmcneill#define PART_SIZE_COL	(PART_MOUNT_COL + MAX_MOUNT_NAME + 3)
240297627Sjmcneill#define PART_NEWFS_COL	(PART_SIZE_COL + 7)
241297627Sjmcneill#define PART_OFF	38
242297627Sjmcneill
243297627Sjmcneill/* How many mounted partitions to display in column before going to next */
244297627Sjmcneill#define CHUNK_COLUMN_MAX	6
245297627Sjmcneill
246297627Sjmcneillstatic void
247297627Sjmcneillprint_fbsd_chunks(void)
248297627Sjmcneill{
249297627Sjmcneill    int i, j, srow, prow, pcol;
250297627Sjmcneill    int sz;
251297627Sjmcneill
252297627Sjmcneill    attrset(A_REVERSE);
253297627Sjmcneill    mvaddstr(0, 25, "FreeBSD Partition Editor");
254297627Sjmcneill    attrset(A_NORMAL);
255297627Sjmcneill
256297627Sjmcneill    for (i = 0; i < 2; i++) {
257297627Sjmcneill	attrset(A_UNDERLINE);
258297627Sjmcneill	mvaddstr(CHUNK_PART_START_ROW - 1, PART_PART_COL + (i * PART_OFF),
259297627Sjmcneill		 "Part");
260297627Sjmcneill	attrset(A_NORMAL);
261297627Sjmcneill
262297627Sjmcneill	attrset(A_UNDERLINE);
263297627Sjmcneill	mvaddstr(CHUNK_PART_START_ROW - 1, PART_MOUNT_COL + (i * PART_OFF),
264297627Sjmcneill		 "Mount");
265297627Sjmcneill	attrset(A_NORMAL);
266297627Sjmcneill
267297627Sjmcneill	attrset(A_UNDERLINE);
268297627Sjmcneill	mvaddstr(CHUNK_PART_START_ROW - 1, PART_SIZE_COL + (i * PART_OFF) + 2,
269297627Sjmcneill		 "Size");
270297627Sjmcneill	attrset(A_NORMAL);
271297627Sjmcneill
272297627Sjmcneill	attrset(A_UNDERLINE);
273297627Sjmcneill	mvaddstr(CHUNK_PART_START_ROW - 1, PART_NEWFS_COL + (i * PART_OFF),
274297627Sjmcneill		 "Newfs");
275297627Sjmcneill	attrset(A_NORMAL);
276297627Sjmcneill    }
277297627Sjmcneill
278297627Sjmcneill    srow = CHUNK_SLICE_START_ROW;
279297627Sjmcneill    prow = CHUNK_PART_START_ROW;
280297627Sjmcneill    pcol = 0;
281297627Sjmcneill
282297627Sjmcneill    for (i = 0; fbsd_chunk_info[i].d; i++) {
283297627Sjmcneill	if (i == current_chunk)
284297627Sjmcneill	    attrset(A_REVERSE);
285297627Sjmcneill	/* Is it a slice entry displayed at the top? */
286297627Sjmcneill	if (fbsd_chunk_info[i].type == PART_SLICE) {
287297627Sjmcneill	    sz = space_free(fbsd_chunk_info[i].c);
288297627Sjmcneill	    mvprintw(srow++, 0,
289297627Sjmcneill		     "Disk: %s\tPartition name: %s\tFree: %d blocks (%dMB)",
290297627Sjmcneill		     fbsd_chunk_info[i].d->name,
291297627Sjmcneill		     fbsd_chunk_info[i].c->name, sz, (sz / 2048));
292297627Sjmcneill	}
293297627Sjmcneill	/* Otherwise it's a swap or filesystem entry, at the bottom */
294297627Sjmcneill	else {
295297627Sjmcneill	    char onestr[PART_OFF], num[10], *mountpoint, *newfs;
296297627Sjmcneill
297297627Sjmcneill	    memset(onestr, ' ', PART_OFF - 1);
298297627Sjmcneill	    onestr[PART_OFF - 1] = '\0';
299297627Sjmcneill	    /* Go for two columns */
300297627Sjmcneill	    if (prow == (CHUNK_PART_START_ROW + CHUNK_COLUMN_MAX)) {
301297627Sjmcneill		pcol = PART_OFF;
302297627Sjmcneill		prow = CHUNK_PART_START_ROW;
303297627Sjmcneill	    }
304297627Sjmcneill	    memcpy(onestr + PART_PART_COL, fbsd_chunk_info[i].c->name,
305297627Sjmcneill		   strlen(fbsd_chunk_info[i].c->name));
306297627Sjmcneill	    if (fbsd_chunk_info[i].type == PART_FILESYSTEM) {
307297627Sjmcneill		if (fbsd_chunk_info[i].c->private) {
308297627Sjmcneill		    mountpoint = ((PartInfo *)fbsd_chunk_info[i].c->private)->mountpoint;
309297627Sjmcneill		    newfs = ((PartInfo *)fbsd_chunk_info[i].c->private)->newfs ? "Y" : "N";
310297627Sjmcneill		}
311297627Sjmcneill		else {
312297627Sjmcneill		    fbsd_chunk_info[i].c->private = new_part("", FALSE);
313297627Sjmcneill		    fbsd_chunk_info[i].c->private_free = safe_free;
314297627Sjmcneill		    mountpoint = " ";
315297627Sjmcneill		    newfs = "N";
316297627Sjmcneill		}
317297627Sjmcneill	    }
318297627Sjmcneill	    else {
319297627Sjmcneill		mountpoint = "swap";
320297627Sjmcneill		newfs = " ";
321297627Sjmcneill	    }
322297627Sjmcneill	    for (j = 0; j < MAX_MOUNT_NAME && mountpoint[j]; j++)
323297627Sjmcneill		onestr[PART_MOUNT_COL + j] = mountpoint[j];
324297627Sjmcneill	    sprintf(num, "%4ldMB", fbsd_chunk_info[i].c->size ?
325297627Sjmcneill		    fbsd_chunk_info[i].c->size / 2048 : 0);
326297627Sjmcneill	    memcpy(onestr + PART_SIZE_COL, num, strlen(num));
327297627Sjmcneill	    memcpy(onestr + PART_NEWFS_COL, newfs, strlen(newfs));
328297627Sjmcneill	    mvaddstr(prow, pcol, onestr);
329297627Sjmcneill	    ++prow;
330297627Sjmcneill	}
331297627Sjmcneill	if (i == current_chunk)
332297627Sjmcneill	    attrset(A_NORMAL);
333297627Sjmcneill    }
334297627Sjmcneill}
335297627Sjmcneill
336297627Sjmcneillstatic void
337297627Sjmcneillprint_command_summary()
338297627Sjmcneill{
339297627Sjmcneill    mvprintw(17, 0,
340297627Sjmcneill	     "The following commands are valid here (upper or lower case):");
341297627Sjmcneill    mvprintw(19, 0, "C = Create Partition   D = Delete Partition   M = Mount Partition");
342297627Sjmcneill    mvprintw(20, 0, "N = Newfs Options      T = Toggle Newfs       ESC = Finish Partitioning");
343297627Sjmcneill    mvprintw(21, 0, "The default target will be displayed in ");
344297627Sjmcneill
345297627Sjmcneill    attrset(A_REVERSE);
346297627Sjmcneill    addstr("reverse video");
347297627Sjmcneill    attrset(A_NORMAL);
348297627Sjmcneill    mvprintw(22, 0, "Use F1 or ? to get more help");
349297627Sjmcneill    move(0, 0);
350297627Sjmcneill}
351297627Sjmcneill
352297627Sjmcneillvoid
353297627Sjmcneillpartition_disks(void)
354297627Sjmcneill{
355297627Sjmcneill    int sz, key = 0;
356297627Sjmcneill    Boolean partitioning;
357297627Sjmcneill    char *msg = NULL;
358297627Sjmcneill    PartInfo *p;
359297627Sjmcneill    PartType type;
360297627Sjmcneill
361297627Sjmcneill    dialog_clear();
362297627Sjmcneill    partitioning = TRUE;
363297627Sjmcneill    keypad(stdscr, TRUE);
364297627Sjmcneill    record_fbsd_chunks();
365297627Sjmcneill
366297627Sjmcneill    while (partitioning) {
367297627Sjmcneill	clear();
368297627Sjmcneill	print_fbsd_chunks();
369297627Sjmcneill	print_command_summary();
370297627Sjmcneill	if (msg) {
371297627Sjmcneill	    attrset(A_REVERSE); mvprintw(23, 0, msg); attrset(A_NORMAL);
372297627Sjmcneill	    beep();
373297627Sjmcneill	    msg = NULL;
374297627Sjmcneill	}
375297627Sjmcneill	refresh();
376297627Sjmcneill	key = toupper(getch());
377297627Sjmcneill	switch (key) {
378297627Sjmcneill
379297627Sjmcneill	case KEY_UP:
380297627Sjmcneill	case '-':
381297627Sjmcneill	    if (current_chunk != 0)
382297627Sjmcneill		--current_chunk;
383297627Sjmcneill	    break;
384297627Sjmcneill
385297627Sjmcneill	case KEY_DOWN:
386297627Sjmcneill	case '+':
387297627Sjmcneill	case '\r':
388297627Sjmcneill	case '\n':
389297627Sjmcneill	    if (fbsd_chunk_info[current_chunk + 1].d)
390297627Sjmcneill		++current_chunk;
391297627Sjmcneill	    break;
392297627Sjmcneill
393297627Sjmcneill	case KEY_HOME:
394297627Sjmcneill	    current_chunk = 0;
395297627Sjmcneill	    break;
396297627Sjmcneill
397297627Sjmcneill	case KEY_END:
398297627Sjmcneill	    while (fbsd_chunk_info[current_chunk + 1].d)
399297627Sjmcneill		++current_chunk;
400297627Sjmcneill	    break;
401297627Sjmcneill
402297627Sjmcneill	case KEY_F(1):
403297627Sjmcneill	case '?':
404297627Sjmcneill	    systemDisplayFile("partitioning.hlp");
405297627Sjmcneill	    break;
406297627Sjmcneill
407297627Sjmcneill	case 'C':
408297627Sjmcneill	    if (fbsd_chunk_info[current_chunk].type != PART_SLICE) {
409297627Sjmcneill		msg = "You can only do this in a master partition (see top of screen)";
410297627Sjmcneill		break;
411297627Sjmcneill	    }
412297627Sjmcneill	    sz = space_free(fbsd_chunk_info[current_chunk].c);
413297627Sjmcneill	    if (sz <= FS_MIN_SIZE)
414297627Sjmcneill		msg = "Not enough space to create additional FreeBSD partition";
415297627Sjmcneill	    else {
416297627Sjmcneill		char *val, *cp, tmp[20];
417297627Sjmcneill		int size;
418297627Sjmcneill
419297627Sjmcneill		snprintf(tmp, 20, "%d", sz);
420297627Sjmcneill		val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks, or append\na trailing `M' for megabytes (e.g. 20M).");
421297627Sjmcneill		if (val && (size = strtol(val, &cp, 0)) > 0) {
422297627Sjmcneill		    struct chunk *tmp;
423297627Sjmcneill		    u_long flags = 0;
424297627Sjmcneill
425297627Sjmcneill		    if (*cp && toupper(*cp) == 'M')
426297627Sjmcneill			size *= 2048;
427297627Sjmcneill
428297627Sjmcneill		    type = get_partition_type();
429297627Sjmcneill		    if (type == PART_NONE)
430297627Sjmcneill			break;
431297627Sjmcneill		    else if (type == PART_FILESYSTEM) {
432297627Sjmcneill			if ((p = get_mountpoint(NULL)) == NULL)
433297627Sjmcneill			    break;
434297627Sjmcneill			else if (!strcmp(p->mountpoint, "/"))
435297627Sjmcneill			    flags |= CHUNK_IS_ROOT;
436297627Sjmcneill			else
437297627Sjmcneill			    flags &= ~CHUNK_IS_ROOT;
438297627Sjmcneill		    }
439297627Sjmcneill		    else
440297627Sjmcneill			p = NULL;
441297627Sjmcneill
442297627Sjmcneill		    tmp = Create_Chunk_DWIM(fbsd_chunk_info[current_chunk].d,
443297627Sjmcneill					    fbsd_chunk_info[current_chunk].c,
444297627Sjmcneill					    size,
445297627Sjmcneill					    part,
446297627Sjmcneill					    (type == PART_SWAP) ?
447297627Sjmcneill					    FS_SWAP : FS_BSDFFS,
448297627Sjmcneill					    flags);
449297627Sjmcneill		    if (!tmp)
450297627Sjmcneill			msgConfirm("Unable to create the partition.  Too big?");
451297627Sjmcneill		    else {
452297627Sjmcneill			tmp->private = p;
453297627Sjmcneill			tmp->private_free = safe_free;
454297627Sjmcneill			record_fbsd_chunks();
455297627Sjmcneill		    }
456297627Sjmcneill		}
457297627Sjmcneill	    }
458297627Sjmcneill	    break;
459297627Sjmcneill
460297627Sjmcneill	case 'D':	/* delete */
461297627Sjmcneill	    if (fbsd_chunk_info[current_chunk].type == PART_SLICE) {
462297627Sjmcneill		msg = MSG_NOT_APPLICABLE;
463297627Sjmcneill		break;
464297627Sjmcneill	    }
465297627Sjmcneill	    Delete_Chunk(fbsd_chunk_info[current_chunk].d,
466297627Sjmcneill			 fbsd_chunk_info[current_chunk].c);
467297627Sjmcneill	    record_fbsd_chunks();
468297627Sjmcneill	    break;
469297627Sjmcneill
470297627Sjmcneill	case 'M':	/* mount */
471297627Sjmcneill	    switch(fbsd_chunk_info[current_chunk].type) {
472297627Sjmcneill	    case PART_SLICE:
473297627Sjmcneill		msg = MSG_NOT_APPLICABLE;
474297627Sjmcneill		break;
475305436Smanu
476305436Smanu	    case PART_SWAP:
477305436Smanu		msg = "You don't need to specify a mountpoint for a swap partition.";
478305436Smanu		break;
479305436Smanu
480305436Smanu	    case PART_FILESYSTEM:
481305436Smanu		p = get_mountpoint(fbsd_chunk_info[current_chunk].c);
482305436Smanu		if (p) {
483305436Smanu		    p->newfs = FALSE;
484305436Smanu		    record_fbsd_chunks();
485305436Smanu		}
486305436Smanu		break;
487305436Smanu
488305436Smanu	    default:
489305436Smanu		msgFatal("Bogus partition under cursor???");
490305436Smanu		break;
491305436Smanu	    }
492305436Smanu	    break;
493305436Smanu
494305436Smanu	case 'N':	/* Set newfs options */
495305436Smanu	    if (fbsd_chunk_info[current_chunk].c->private &&
496305436Smanu		((PartInfo *)fbsd_chunk_info[current_chunk].c->private)->newfs)
497305436Smanu		getNewfsCmd(fbsd_chunk_info[current_chunk].c->private);
498305436Smanu	    else
499305436Smanu		msg = MSG_NOT_APPLICABLE;
500305436Smanu	    break;
501305436Smanu
502305436Smanu	case 'T':	/* Toggle newfs state */
503305436Smanu	    if (fbsd_chunk_info[current_chunk].c->private)
504305436Smanu		((PartInfo *)fbsd_chunk_info[current_chunk].c->private)->newfs = !((PartInfo *)fbsd_chunk_info[current_chunk].c->private)->newfs;
505305436Smanu	    else
506305436Smanu		msg = MSG_NOT_APPLICABLE;
507305436Smanu	    break;
508305436Smanu
509305436Smanu	case 'W':
510305436Smanu	    if (!msgYesNo("Are you sure you want to go into Wizard mode?\n\nThis is an entirely undocumented feature which you are not\nexpected to understand!")) {
511305436Smanu		int i;
512305436Smanu
513305436Smanu		clear();
514305436Smanu		dialog_clear();
515305436Smanu		end_dialog();
516305436Smanu		DialogActive = FALSE;
517305436Smanu		for (i = 0; Disks[i]; i++)
518305436Smanu		    slice_wizard(Disks[i]);
519305436Smanu		clear();
520305436Smanu		dialog_clear();
521305436Smanu		DialogActive = TRUE;
522305436Smanu		record_fbsd_chunks();
523305436Smanu	    }
524305436Smanu	    else
525305436Smanu		msg = "A most prudent choice!";
526305436Smanu	    break;
527305436Smanu
528305436Smanu	case 27:	/* ESC */
529305436Smanu	    partitioning = FALSE;
530305436Smanu	    break;
531305436Smanu
532305436Smanu	default:
533305436Smanu	    beep();
534305436Smanu	    msg = "Type F1 or ? for help";
535305436Smanu	    break;
536305436Smanu	}
537305436Smanu    }
538305436Smanu}
539305436Smanu
540305436Smanuint
541305436Smanuwrite_disks(void)
542305436Smanu{
543305436Smanu    int i;
544305436Smanu    extern u_char boot1[], boot2[];
545305436Smanu    extern u_char mbr[], bteasy17[];
546305436Smanu
547305436Smanu    dialog_clear();
548305436Smanu    for (i = 0; Disks[i]; i++) {
549305436Smanu	Set_Boot_Blocks(Disks[i], boot1, boot2);
550299688Smanu	dialog_clear();
551299688Smanu	if (i == 0 && !msgYesNo("Would you like to install a boot manager?\n\nThis will allow you to easily select between other operating systems\non the first disk, or boot from a disk other than the first."))
552299688Smanu	    Set_Boot_Mgr(Disks[i], bteasy17);
553299688Smanu	else {
554299688Smanu	    dialog_clear();
555299688Smanu	    if (i == 0 && !msgYesNo("Would you like to remove an existing boot manager?"))
556299688Smanu		Set_Boot_Mgr(Disks[i], mbr);
557299688Smanu	}
558299688Smanu	dialog_clear();
559299688Smanu	if (!msgYesNo("Last Chance!  Are you sure you want to write out\nall these changes to disk?")) {
560299688Smanu	    Write_Disk(Disks[i]);
561299688Smanu	    return 0;
562299688Smanu	}
563299688Smanu    }
564299688Smanu    return 1;
565299688Smanu}
566299688Smanu