xref: /netbsd/usr.sbin/sysinst/label.c (revision b288bf5c)
1*b288bf5cSmartin /*	$NetBSD: label.c,v 1.4 2018/11/20 19:02:07 martin Exp $	*/
226165e63Sdholland 
326165e63Sdholland /*
426165e63Sdholland  * Copyright 1997 Jonathan Stone
526165e63Sdholland  * All rights reserved.
626165e63Sdholland  *
726165e63Sdholland  * Redistribution and use in source and binary forms, with or without
826165e63Sdholland  * modification, are permitted provided that the following conditions
926165e63Sdholland  * are met:
1026165e63Sdholland  * 1. Redistributions of source code must retain the above copyright
1126165e63Sdholland  *    notice, this list of conditions and the following disclaimer.
1226165e63Sdholland  * 2. Redistributions in binary form must reproduce the above copyright
1326165e63Sdholland  *    notice, this list of conditions and the following disclaimer in the
1426165e63Sdholland  *    documentation and/or other materials provided with the distribution.
1526165e63Sdholland  * 3. All advertising materials mentioning features or use of this software
1626165e63Sdholland  *    must display the following acknowledgement:
1726165e63Sdholland  *      This product includes software developed for the NetBSD Project by
1826165e63Sdholland  *      Jonathan Stone.
1926165e63Sdholland  * 4. The name of Jonathan Stone may not be used to endorse
2026165e63Sdholland  *    or promote products derived from this software without specific prior
2126165e63Sdholland  *    written permission.
2226165e63Sdholland  *
2326165e63Sdholland  * THIS SOFTWARE IS PROVIDED BY JONATHAN STONE ``AS IS''
2426165e63Sdholland  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2526165e63Sdholland  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2626165e63Sdholland  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
2726165e63Sdholland  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2826165e63Sdholland  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2926165e63Sdholland  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3026165e63Sdholland  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3126165e63Sdholland  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3226165e63Sdholland  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3326165e63Sdholland  * THE POSSIBILITY OF SUCH DAMAGE.
3426165e63Sdholland  *
3526165e63Sdholland  */
3626165e63Sdholland 
3726165e63Sdholland #include <sys/cdefs.h>
3826165e63Sdholland #if defined(LIBC_SCCS) && !defined(lint)
39*b288bf5cSmartin __RCSID("$NetBSD: label.c,v 1.4 2018/11/20 19:02:07 martin Exp $");
4026165e63Sdholland #endif
4126165e63Sdholland 
4226165e63Sdholland #include <sys/types.h>
4326165e63Sdholland #include <stddef.h>
4426165e63Sdholland #include <errno.h>
4526165e63Sdholland #include <stdio.h>
4626165e63Sdholland #include <fcntl.h>
4726165e63Sdholland #include <util.h>
4826165e63Sdholland #include <unistd.h>
4926165e63Sdholland #include <sys/dkio.h>
5026165e63Sdholland #include <sys/param.h>
5126165e63Sdholland #include <ufs/ffs/fs.h>
5226165e63Sdholland 
5326165e63Sdholland #include "defs.h"
5426165e63Sdholland #include "msg_defs.h"
5526165e63Sdholland #include "menu_defs.h"
5626165e63Sdholland 
5726165e63Sdholland struct ptn_menu_info {
5826165e63Sdholland 	int	flags;
5926165e63Sdholland #define PIF_SHOW_UNUSED		1
6026165e63Sdholland };
6126165e63Sdholland 
6226165e63Sdholland /*
6326165e63Sdholland  * local prototypes
6426165e63Sdholland  */
6526165e63Sdholland static int boringpart(partinfo *, int, int, int);
6626165e63Sdholland static uint32_t getpartoff(uint32_t);
6726165e63Sdholland static uint32_t getpartsize(uint32_t, uint32_t);
6826165e63Sdholland 
6926165e63Sdholland static int	checklabel(partinfo *, int, int, int, int *, int *);
7026165e63Sdholland static int	atofsb(const char *, uint32_t *, uint32_t *);
7126165e63Sdholland 
7226165e63Sdholland 
7326165e63Sdholland /*
7426165e63Sdholland  * Return 1 if partition i in lp should be ignored when checking
7526165e63Sdholland  * for overlapping partitions.
7626165e63Sdholland  */
7726165e63Sdholland static int
7826165e63Sdholland boringpart(partinfo *lp, int i, int rawpart, int bsdpart)
7926165e63Sdholland {
8026165e63Sdholland 
8126165e63Sdholland 	if (i == rawpart || i == bsdpart ||
8226165e63Sdholland 	    lp[i].pi_fstype == FS_UNUSED || lp[i].pi_size == 0)
8326165e63Sdholland 		return 1;
8426165e63Sdholland 	return 0;
8526165e63Sdholland }
8626165e63Sdholland 
8726165e63Sdholland 
8826165e63Sdholland 
8926165e63Sdholland /*
9026165e63Sdholland  * Check a sysinst label structure for overlapping partitions.
9126165e63Sdholland  * Returns 0 if no overlapping partition found, nonzero otherwise.
9226165e63Sdholland  * Sets reference arguments ovly1 and ovly2 to the indices of
9326165e63Sdholland  * overlapping partitions if any are found.
9426165e63Sdholland  */
9526165e63Sdholland static int
9626165e63Sdholland checklabel(partinfo *lp, int nparts, int rawpart, int bsdpart,
9726165e63Sdholland 	int *ovly1, int *ovly2)
9826165e63Sdholland {
9926165e63Sdholland 	int i;
10026165e63Sdholland 	int j;
10126165e63Sdholland 
10226165e63Sdholland 	*ovly1 = -1;
10326165e63Sdholland 	*ovly2 = -1;
10426165e63Sdholland 
10526165e63Sdholland 	for (i = 0; i < nparts - 1; i ++ ) {
10626165e63Sdholland 		partinfo *ip = &lp[i];
10726165e63Sdholland 		uint32_t istart, istop;
10826165e63Sdholland 
10926165e63Sdholland 		/* skip unused or reserved partitions */
11026165e63Sdholland 		if (boringpart(lp, i, rawpart, bsdpart))
11126165e63Sdholland 			continue;
11226165e63Sdholland 
11326165e63Sdholland 		/*
11426165e63Sdholland 		 * check succeeding partitions for overlap.
11526165e63Sdholland 		 * O(n^2), but n is small (currently <= 16).
11626165e63Sdholland 		 */
11726165e63Sdholland 		istart = ip->pi_offset;
11826165e63Sdholland 		istop = istart + ip->pi_size;
11926165e63Sdholland 
12026165e63Sdholland 		for (j = i+1; j < nparts; j++) {
12126165e63Sdholland 			partinfo *jp = &lp[j];
12226165e63Sdholland 			uint32_t jstart, jstop;
12326165e63Sdholland 
12426165e63Sdholland 			/* skip unused or reserved partitions */
12526165e63Sdholland 			if (boringpart(lp, j, rawpart, bsdpart))
12626165e63Sdholland 				continue;
12726165e63Sdholland 
12826165e63Sdholland 			jstart = jp->pi_offset;
12926165e63Sdholland 			jstop = jstart + jp->pi_size;
13026165e63Sdholland 
13126165e63Sdholland 			/* overlap? */
13226165e63Sdholland 			if ((istart <= jstart && jstart < istop) ||
13326165e63Sdholland 			    (jstart <= istart && istart < jstop)) {
13426165e63Sdholland 				*ovly1 = i;
13526165e63Sdholland 				*ovly2 = j;
13626165e63Sdholland 				return (1);
13726165e63Sdholland 			}
13826165e63Sdholland 		}
13926165e63Sdholland 	}
14026165e63Sdholland 
14126165e63Sdholland 	return (0);
14226165e63Sdholland }
14326165e63Sdholland 
144da5a563bSmartin int
145da5a563bSmartin checkoverlap(partinfo *lp, int nparts, int rawpart, int bsdpart)
146da5a563bSmartin {
147da5a563bSmartin 	int i, j;
148da5a563bSmartin 	if (checklabel(lp, nparts, rawpart, bsdpart, &i, &j)) {
149da5a563bSmartin 		msg_display(MSG_partitions_overlap,'a'+i,'a'+j);
150da5a563bSmartin 		return 1;
151da5a563bSmartin 	}
152da5a563bSmartin 	return 0;
153da5a563bSmartin }
154da5a563bSmartin 
15526165e63Sdholland static int
15626165e63Sdholland check_one_root(partinfo *lp, int nparts)
15726165e63Sdholland {
15826165e63Sdholland 	int part;
15926165e63Sdholland 	int foundroot = 0;
16026165e63Sdholland 
16126165e63Sdholland 	for (part = 0; part < nparts; lp++, part++) {
16226165e63Sdholland #if 0
16326165e63Sdholland 		if (!PI_ISBSDFS(lp))
16426165e63Sdholland 			continue;
16526165e63Sdholland #endif
16626165e63Sdholland 		if (!(lp->pi_flags & PIF_MOUNT))
16726165e63Sdholland 			continue;
16826165e63Sdholland 		if (strcmp(lp->pi_mount, "/") != 0)
16926165e63Sdholland 			continue;
17026165e63Sdholland 		if (foundroot)
17126165e63Sdholland 			/* Duplicate */
17226165e63Sdholland 			return 0;
17326165e63Sdholland 		foundroot = 1;
17426165e63Sdholland 		/* Save partition number, a few things need to know it */
175da5a563bSmartin 		pm->rootpart = part;
17626165e63Sdholland 	}
17726165e63Sdholland 	return foundroot;
17826165e63Sdholland }
17926165e63Sdholland 
18026165e63Sdholland static int
18126165e63Sdholland edit_fs_start(menudesc *m, void *arg)
18226165e63Sdholland {
18326165e63Sdholland 	partinfo *p = arg;
18426165e63Sdholland 	uint32_t start, end;
18526165e63Sdholland 
18626165e63Sdholland 	start = getpartoff(p->pi_offset);
18726165e63Sdholland 	if (p->pi_size != 0) {
18826165e63Sdholland 		/* Try to keep end in the same place */
18926165e63Sdholland 		end = p->pi_offset + p->pi_size;
19026165e63Sdholland 		if (end < start)
19126165e63Sdholland 			p->pi_size = 0;
19226165e63Sdholland 		else
19326165e63Sdholland 			p->pi_size = end - start;
19426165e63Sdholland 	}
19526165e63Sdholland 	p->pi_offset = start;
19626165e63Sdholland 	return 0;
19726165e63Sdholland }
19826165e63Sdholland 
19926165e63Sdholland static int
20026165e63Sdholland edit_fs_size(menudesc *m, void *arg)
20126165e63Sdholland {
20226165e63Sdholland 	partinfo *p = arg;
20326165e63Sdholland 	uint32_t size;
20426165e63Sdholland 
20526165e63Sdholland 	size = getpartsize(p->pi_offset, p->pi_size);
20626165e63Sdholland 	if (size == ~0u)
207da5a563bSmartin 		size = pm->dlsize - p->pi_offset;
20826165e63Sdholland 	p->pi_size = size;
20926165e63Sdholland 	if (size == 0) {
21026165e63Sdholland 		p->pi_offset = 0;
21126165e63Sdholland 		p->pi_fstype = FS_UNUSED;
21226165e63Sdholland 	}
21326165e63Sdholland 	return 0;
21426165e63Sdholland }
21526165e63Sdholland 
21626165e63Sdholland void
21726165e63Sdholland set_ptype(partinfo *p, int fstype, int flag)
21826165e63Sdholland {
21926165e63Sdholland 	p->pi_flags = (p->pi_flags & ~PIF_FFSv2) | flag;
22026165e63Sdholland 
22126165e63Sdholland 	if (p->pi_fstype == fstype)
22226165e63Sdholland 		return;
22326165e63Sdholland 
22426165e63Sdholland 	p->pi_fstype = fstype;
22526165e63Sdholland 	if (fstype == FS_BSDFFS || fstype == FS_BSDLFS) {
22626165e63Sdholland 		p->pi_frag = 8;
22726165e63Sdholland 		/*
22826165e63Sdholland 		 * match newfs defaults for fragments size:
22926165e63Sdholland 		 * fs size	frag size
23026165e63Sdholland 		 * < 20 MB	0.5 KB
23126165e63Sdholland 		 * < 1000 MB	1 KB
23226165e63Sdholland 		 * < 128 GB	2 KB
23326165e63Sdholland 		 * >= 128 GB	4 KB
23426165e63Sdholland 		 */
23526165e63Sdholland 	 	/* note pi_size is uint32_t so we have to avoid overflow */
23626165e63Sdholland 		if (p->pi_size < (20 * 1024 * (1024 / 512)))
23726165e63Sdholland 			p->pi_fsize = 512;
23826165e63Sdholland 		else if (p->pi_size < (1000 * 1024 * (1024 / 512)))
23926165e63Sdholland 			p->pi_fsize = 1024;
24026165e63Sdholland 		else if (p->pi_size < (128 * 1024 * 1024 * (1024 / 512)))
24126165e63Sdholland 			p->pi_fsize = 2048;
24226165e63Sdholland 		else
24326165e63Sdholland 			p->pi_fsize = 4096;
24426165e63Sdholland 	} else {
24526165e63Sdholland 		/* zero - fields not used */
24626165e63Sdholland 		p->pi_frag = 0;
24726165e63Sdholland 		p->pi_fsize = 0;
24826165e63Sdholland 	}
24926165e63Sdholland }
25026165e63Sdholland 
25126165e63Sdholland void
25226165e63Sdholland set_bsize(partinfo *p, int size)
25326165e63Sdholland {
25426165e63Sdholland 	int frags, sz;
25526165e63Sdholland 
25626165e63Sdholland 	sz = p->pi_fsize;
25726165e63Sdholland 	if (sz <= 0)
25826165e63Sdholland 		sz = 512;
25926165e63Sdholland 	frags = size / sz;
26026165e63Sdholland 	if (frags > 8)
26126165e63Sdholland 		frags = 8;
26226165e63Sdholland 	if (frags <= 0)
26326165e63Sdholland 		frags = 1;
26426165e63Sdholland 
26526165e63Sdholland 	p->pi_frag = frags;
26626165e63Sdholland 	p->pi_fsize = size / frags;
26726165e63Sdholland }
26826165e63Sdholland 
26926165e63Sdholland void
27026165e63Sdholland set_fsize(partinfo *p, int fsize)
27126165e63Sdholland {
27226165e63Sdholland 	int bsz = p->pi_fsize * p->pi_frag;
27326165e63Sdholland 	int frags = bsz / fsize;
27426165e63Sdholland 
27526165e63Sdholland 	if (frags > 8)
27626165e63Sdholland 		frags = 8;
27726165e63Sdholland 	if (frags <= 0)
27826165e63Sdholland 		frags = 1;
27926165e63Sdholland 
28026165e63Sdholland 	p->pi_fsize = fsize;
28126165e63Sdholland 	p->pi_frag = frags;
28226165e63Sdholland }
28326165e63Sdholland 
28426165e63Sdholland static int
28526165e63Sdholland edit_fs_isize(menudesc *m, void *arg)
28626165e63Sdholland {
28726165e63Sdholland 	partinfo *p = arg;
28826165e63Sdholland 	char answer[12];
28926165e63Sdholland 
29026165e63Sdholland 	snprintf(answer, sizeof answer, "%u", p->pi_isize);
29126165e63Sdholland 	msg_prompt_win(MSG_fs_isize, -1, 18, 0, 0,
29226165e63Sdholland 		answer, answer, sizeof answer);
29326165e63Sdholland 	p->pi_isize = atol(answer);
29426165e63Sdholland 	return 0;
29526165e63Sdholland }
29626165e63Sdholland 
29726165e63Sdholland 
29826165e63Sdholland static int
29926165e63Sdholland edit_fs_preserve(menudesc *m, void *arg)
30026165e63Sdholland {
30126165e63Sdholland 	partinfo *p = arg;
30226165e63Sdholland 
30326165e63Sdholland 	p->pi_flags ^= PIF_NEWFS;
30426165e63Sdholland 	return 0;
30526165e63Sdholland }
30626165e63Sdholland 
30726165e63Sdholland static int
30826165e63Sdholland edit_fs_mount(menudesc *m, void *arg)
30926165e63Sdholland {
31026165e63Sdholland 	partinfo *p = arg;
31126165e63Sdholland 
31226165e63Sdholland 	p->pi_flags ^= PIF_MOUNT;
31326165e63Sdholland 	return 0;
31426165e63Sdholland }
31526165e63Sdholland 
31626165e63Sdholland static int
31726165e63Sdholland edit_fs_mountpt(menudesc *m, void *arg)
31826165e63Sdholland {
31926165e63Sdholland 	partinfo *p = arg;
32026165e63Sdholland 
32126165e63Sdholland 	msg_prompt_win(MSG_mountpoint, -1, 18, 0, 0,
32226165e63Sdholland 		p->pi_mount, p->pi_mount, sizeof p->pi_mount);
32326165e63Sdholland 
32426165e63Sdholland 	if (p->pi_mount[0] == ' ' || strcmp(p->pi_mount, "none") == 0) {
32526165e63Sdholland 		p->pi_mount[0] = 0;
32626165e63Sdholland 		return 0;
32726165e63Sdholland 	}
32826165e63Sdholland 
32926165e63Sdholland 	if (p->pi_mount[0] != '/') {
33026165e63Sdholland 		memmove(p->pi_mount + 1, p->pi_mount,
33126165e63Sdholland 		    sizeof p->pi_mount - 1);
33226165e63Sdholland 		p->pi_mount[sizeof p->pi_mount - 1] = 0;
33326165e63Sdholland 		p->pi_mount[0] = '/';
33426165e63Sdholland 	}
33526165e63Sdholland 
33626165e63Sdholland 	return 0;
33726165e63Sdholland }
33826165e63Sdholland 
33926165e63Sdholland static int
34026165e63Sdholland edit_restore(menudesc *m, void *arg)
34126165e63Sdholland {
34226165e63Sdholland 	partinfo *p = arg;
34326165e63Sdholland 
34426165e63Sdholland 	p->pi_flags |= PIF_RESET;
34526165e63Sdholland 	return 1;
34626165e63Sdholland }
34726165e63Sdholland 
34826165e63Sdholland static int
34926165e63Sdholland set_fstype(menudesc *m, void *arg)
35026165e63Sdholland {
35126165e63Sdholland 	partinfo *p = arg;
35226165e63Sdholland 
35326165e63Sdholland 	if (m->cursel == FS_UNUSED)
35426165e63Sdholland 		memset(p, 0, sizeof *p);
35526165e63Sdholland 	else
35626165e63Sdholland 		p->pi_fstype = m->cursel;
35726165e63Sdholland 	return 1;
35826165e63Sdholland }
35926165e63Sdholland 
36026165e63Sdholland static void
36126165e63Sdholland get_fstype(menudesc *m, void *arg)
36226165e63Sdholland {
36326165e63Sdholland 	partinfo *p = arg;
36426165e63Sdholland 
36526165e63Sdholland 	m->cursel = p->pi_fstype;
36626165e63Sdholland }
36726165e63Sdholland 
36826165e63Sdholland static void set_ptn_header(menudesc *m, void *arg);
36926165e63Sdholland static void set_ptn_label(menudesc *m, int opt, void *arg);
37026165e63Sdholland int all_fstype_menu = -1;
37126165e63Sdholland 
372da5a563bSmartin int
37326165e63Sdholland edit_ptn(menudesc *menu, void *arg)
37426165e63Sdholland {
37526165e63Sdholland 	static menu_ent fs_fields[] = {
37626165e63Sdholland #define PTN_MENU_FSKIND		0
377*b288bf5cSmartin 	    { .opt_menu=MENU_selfskind, .opt_flags=OPT_SUB },
37826165e63Sdholland #define PTN_MENU_START		1
379*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_start },
38026165e63Sdholland #define PTN_MENU_SIZE		2
381*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_size },
38226165e63Sdholland #define PTN_MENU_END		3
383*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_flags=OPT_IGNORE },	/* displays 'end' */
38426165e63Sdholland #define PTN_MENU_NEWFS		4
385*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_preserve },
38626165e63Sdholland #define PTN_MENU_ISIZE		5
387*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_isize },
38826165e63Sdholland #define PTN_MENU_BSIZE		6
389*b288bf5cSmartin 	    { .opt_menu=MENU_selbsize, .opt_flags=OPT_SUB },
39026165e63Sdholland #define PTN_MENU_FSIZE		7
391*b288bf5cSmartin 	    { .opt_menu=MENU_selfsize, .opt_flags=OPT_SUB },
39226165e63Sdholland #define PTN_MENU_MOUNT		8
393*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_mount },
39426165e63Sdholland #define PTN_MENU_MOUNTOPT	9
395*b288bf5cSmartin 	    { .opt_menu=MENU_mountoptions, .opt_flags=OPT_SUB },
39626165e63Sdholland #define PTN_MENU_MOUNTPT	10
397*b288bf5cSmartin 	    { .opt_menu=OPT_NOMENU, .opt_action=edit_fs_mountpt },
398*b288bf5cSmartin 	    { .opt_name=MSG_askunits, .opt_menu=MENU_sizechoice,
399*b288bf5cSmartin 	      .opt_flags=OPT_SUB },
400*b288bf5cSmartin 	    { .opt_name=MSG_restore, .opt_menu=OPT_NOMENU,
401*b288bf5cSmartin 	      .opt_action=edit_restore},
40226165e63Sdholland 	};
40326165e63Sdholland 	static int fspart_menu = -1;
40426165e63Sdholland 	static menu_ent all_fstypes[FSMAXTYPES];
40526165e63Sdholland 	partinfo *p, p_save;
40626165e63Sdholland 	unsigned int i;
40726165e63Sdholland 
40826165e63Sdholland 	if (fspart_menu == -1) {
40926165e63Sdholland 		fspart_menu = new_menu(NULL, fs_fields, nelem(fs_fields),
41026165e63Sdholland 			0, -1, 0, 70,
41126165e63Sdholland 			MC_NOBOX | MC_NOCLEAR | MC_SCROLL,
41226165e63Sdholland 			set_ptn_header, set_ptn_label, NULL,
41326165e63Sdholland 			NULL, MSG_partition_sizes_ok);
41426165e63Sdholland 	}
41526165e63Sdholland 
41626165e63Sdholland 	if (all_fstype_menu == -1) {
41726165e63Sdholland 		for (i = 0; i < nelem(all_fstypes); i++) {
41826165e63Sdholland 			all_fstypes[i].opt_name = getfslabelname(i);
41926165e63Sdholland 			all_fstypes[i].opt_menu = OPT_NOMENU;
42026165e63Sdholland 			all_fstypes[i].opt_flags = 0;
42126165e63Sdholland 			all_fstypes[i].opt_action = set_fstype;
42226165e63Sdholland 		}
42326165e63Sdholland 		all_fstype_menu = new_menu(MSG_Select_the_type,
42426165e63Sdholland 			all_fstypes, nelem(all_fstypes),
42526165e63Sdholland 			30, 6, 10, 0, MC_SUBMENU | MC_SCROLL,
42626165e63Sdholland 			get_fstype, NULL, NULL, NULL, MSG_unchanged);
42726165e63Sdholland 	}
42826165e63Sdholland 
429da5a563bSmartin 	p = pm->bsdlabel + menu->cursel;
43026165e63Sdholland 	p->pi_flags &= ~PIF_RESET;
43126165e63Sdholland 	p_save = *p;
43226165e63Sdholland 	for (;;) {
43326165e63Sdholland 		process_menu(fspart_menu, p);
43426165e63Sdholland 		if (!(p->pi_flags & PIF_RESET))
43526165e63Sdholland 			break;
43626165e63Sdholland 		*p = p_save;
43726165e63Sdholland 	}
43826165e63Sdholland 
43926165e63Sdholland 	return 0;
44026165e63Sdholland }
44126165e63Sdholland 
44226165e63Sdholland static void
44326165e63Sdholland set_ptn_header(menudesc *m, void *arg)
44426165e63Sdholland {
44526165e63Sdholland 	partinfo *p = arg;
44626165e63Sdholland 	int i;
44726165e63Sdholland 	int t;
44826165e63Sdholland 
44926165e63Sdholland 	msg_clear();
450da5a563bSmartin 	msg_table_add(MSG_edfspart, 'a' + (p - pm->bsdlabel));
45126165e63Sdholland 
45226165e63Sdholland 	/* Determine which of the properties can be changed */
45326165e63Sdholland 	for (i = PTN_MENU_START; i <= PTN_MENU_MOUNTPT; i++) {
45426165e63Sdholland 		/* Default to disabled... */
45526165e63Sdholland 		m->opts[i].opt_flags |= OPT_IGNORE;
45626165e63Sdholland 		t = p->pi_fstype;
45726165e63Sdholland 		if (i == PTN_MENU_END)
45826165e63Sdholland 			/* The 'end address' is calculated from the size */
45926165e63Sdholland 			continue;
46026165e63Sdholland 		if (t == FS_UNUSED || (t == FS_SWAP && i > PTN_MENU_END)) {
46126165e63Sdholland 			/* Nothing after 'size' can be set for swap/unused */
46226165e63Sdholland 			p->pi_flags &= ~(PIF_NEWFS | PIF_MOUNT);
46326165e63Sdholland 			p->pi_mount[0] = 0;
46426165e63Sdholland 			continue;
46526165e63Sdholland 		}
46626165e63Sdholland 		if (i == PTN_MENU_NEWFS && t != FS_BSDFFS && t != FS_BSDLFS
46726165e63Sdholland 		    && t != FS_APPLEUFS) {
46826165e63Sdholland 			/* Can only newfs UFS and LFS filesystems */
46926165e63Sdholland 			p->pi_flags &= ~PIF_NEWFS;
47026165e63Sdholland 			continue;
47126165e63Sdholland 		}
47226165e63Sdholland 		if (i >= PTN_MENU_ISIZE && i <= PTN_MENU_FSIZE) {
47326165e63Sdholland 			/* Parameters for newfs... */
47426165e63Sdholland 			if (!(p->pi_flags & PIF_NEWFS))
47526165e63Sdholland 				/* Not if we aren't going to run newfs */
47626165e63Sdholland 				continue;
47726165e63Sdholland 			 if (t == FS_APPLEUFS && i != PTN_MENU_ISIZE)
47826165e63Sdholland 				/* Can only set # inodes for appleufs */
47926165e63Sdholland 				continue;
48026165e63Sdholland 			 if (t == FS_BSDLFS && i != PTN_MENU_BSIZE)
48126165e63Sdholland 				/* LFS doesn't have fragments */
48226165e63Sdholland 				continue;
48326165e63Sdholland 		}
48426165e63Sdholland 		/* Ok: we want this one */
48526165e63Sdholland 		m->opts[i].opt_flags &= ~OPT_IGNORE;
48626165e63Sdholland 	}
48726165e63Sdholland }
48826165e63Sdholland 
48926165e63Sdholland static void
49026165e63Sdholland disp_sector_count(menudesc *m, msg fmt, uint s)
49126165e63Sdholland {
492da5a563bSmartin 	uint ms = MEG / pm->sectorsize;
49326165e63Sdholland 
49426165e63Sdholland 	wprintw(m->mw, msg_string(fmt),
495da5a563bSmartin 		s / ms, s / pm->dlcylsize, s % pm->dlcylsize ? '*' : ' ', s );
49626165e63Sdholland }
49726165e63Sdholland 
49826165e63Sdholland static void
49926165e63Sdholland set_ptn_label(menudesc *m, int opt, void *arg)
50026165e63Sdholland {
50126165e63Sdholland 	partinfo *p = arg;
50226165e63Sdholland 	const char *c;
50326165e63Sdholland 
50426165e63Sdholland 	if (m->opts[opt].opt_flags & OPT_IGNORE
50526165e63Sdholland 	    && (opt != PTN_MENU_END || p->pi_fstype == FS_UNUSED)) {
50626165e63Sdholland 		wprintw(m->mw, "            -");
50726165e63Sdholland 		return;
50826165e63Sdholland 	}
50926165e63Sdholland 
51026165e63Sdholland 	switch (opt) {
51126165e63Sdholland 	case PTN_MENU_FSKIND:
51226165e63Sdholland 		if (p->pi_fstype == FS_BSDFFS)
51326165e63Sdholland 			if (p->pi_flags & PIF_FFSv2)
51426165e63Sdholland 				c = "FFSv2";
51526165e63Sdholland 			else
51626165e63Sdholland 				c = "FFSv1";
51726165e63Sdholland 		else
51826165e63Sdholland 			c = getfslabelname(p->pi_fstype);
51926165e63Sdholland 		wprintw(m->mw, msg_string(MSG_fstype_fmt), c);
52026165e63Sdholland 		break;
52126165e63Sdholland 	case PTN_MENU_START:
52226165e63Sdholland 		disp_sector_count(m, MSG_start_fmt, p->pi_offset);
52326165e63Sdholland 		break;
52426165e63Sdholland 	case PTN_MENU_SIZE:
52526165e63Sdholland 		disp_sector_count(m, MSG_size_fmt, p->pi_size);
52626165e63Sdholland 		break;
52726165e63Sdholland 	case PTN_MENU_END:
52826165e63Sdholland 		disp_sector_count(m, MSG_end_fmt, p->pi_offset + p->pi_size);
52926165e63Sdholland 		break;
53026165e63Sdholland 	case PTN_MENU_NEWFS:
53126165e63Sdholland 		wprintw(m->mw, msg_string(MSG_newfs_fmt),
53226165e63Sdholland 			msg_string(p->pi_flags & PIF_NEWFS ? MSG_Yes : MSG_No));
53326165e63Sdholland 		break;
53426165e63Sdholland 	case PTN_MENU_ISIZE:
53526165e63Sdholland 		wprintw(m->mw, msg_string(p->pi_isize > 0 ?
53626165e63Sdholland 			MSG_isize_fmt : MSG_isize_fmt_dflt), p->pi_isize);
53726165e63Sdholland 		break;
53826165e63Sdholland 	case PTN_MENU_BSIZE:
53926165e63Sdholland 		wprintw(m->mw, msg_string(MSG_bsize_fmt),
54026165e63Sdholland 			p->pi_fsize * p->pi_frag);
54126165e63Sdholland 		break;
54226165e63Sdholland 	case PTN_MENU_FSIZE:
54326165e63Sdholland 		wprintw(m->mw, msg_string(MSG_fsize_fmt), p->pi_fsize);
54426165e63Sdholland 		break;
54526165e63Sdholland 	case PTN_MENU_MOUNT:
54626165e63Sdholland 		wprintw(m->mw, msg_string(MSG_mount_fmt),
54726165e63Sdholland 			msg_string(p->pi_flags & PIF_MOUNT ? MSG_Yes : MSG_No));
54826165e63Sdholland 		break;
54926165e63Sdholland 	case PTN_MENU_MOUNTOPT:
55026165e63Sdholland 		wprintw(m->mw, "%s", msg_string(MSG_mount_options_fmt));
55126165e63Sdholland 		if (p->pi_flags & PIF_ASYNC)
55226165e63Sdholland 			wprintw(m->mw, "async ");
55326165e63Sdholland 		if (p->pi_flags & PIF_NOATIME)
55426165e63Sdholland 			wprintw(m->mw, "noatime ");
55526165e63Sdholland 		if (p->pi_flags & PIF_NODEV)
55626165e63Sdholland 			wprintw(m->mw, "nodev ");
55726165e63Sdholland 		if (p->pi_flags & PIF_NODEVMTIME)
55826165e63Sdholland 			wprintw(m->mw, "nodevmtime ");
55926165e63Sdholland 		if (p->pi_flags & PIF_NOEXEC)
56026165e63Sdholland 			wprintw(m->mw, "noexec ");
56126165e63Sdholland 		if (p->pi_flags & PIF_NOSUID)
56226165e63Sdholland 			wprintw(m->mw, "nosuid ");
56326165e63Sdholland 		if (p->pi_flags & PIF_LOG)
56426165e63Sdholland 			wprintw(m->mw, "log ");
56526165e63Sdholland 		break;
56626165e63Sdholland 	case PTN_MENU_MOUNTPT:
56726165e63Sdholland 		wprintw(m->mw, msg_string(MSG_mountpt_fmt), p->pi_mount);
56826165e63Sdholland 		break;
56926165e63Sdholland 	}
57026165e63Sdholland }
57126165e63Sdholland 
57226165e63Sdholland static int
57326165e63Sdholland show_all_unused(menudesc *m, void *arg)
57426165e63Sdholland {
57526165e63Sdholland 	struct ptn_menu_info *pi = arg;
57626165e63Sdholland 
57726165e63Sdholland 	pi->flags |= PIF_SHOW_UNUSED;
57826165e63Sdholland 	return 0;
57926165e63Sdholland }
58026165e63Sdholland 
58126165e63Sdholland static void
58226165e63Sdholland set_label_texts(menudesc *menu, void *arg)
58326165e63Sdholland {
58426165e63Sdholland 	struct ptn_menu_info *pi = arg;
58526165e63Sdholland 	menu_ent *m;
58626165e63Sdholland 	int ptn, show_unused_ptn;
58726165e63Sdholland 	int rawptn = getrawpartition();
58826165e63Sdholland 	int maxpart = getmaxpartitions();
58926165e63Sdholland 
59026165e63Sdholland 	msg_display(MSG_fspart);
59126165e63Sdholland 	msg_table_add(MSG_fspart_header, multname, multname, multname);
59226165e63Sdholland 
59326165e63Sdholland 	for (show_unused_ptn = 0, ptn = 0; ptn < maxpart; ptn++) {
59426165e63Sdholland 		m = &menu->opts[ptn];
59526165e63Sdholland 		m->opt_menu = OPT_NOMENU;
59626165e63Sdholland 		m->opt_name = NULL;
59726165e63Sdholland 		m->opt_action = edit_ptn;
59826165e63Sdholland 		if (ptn == rawptn
59926165e63Sdholland #ifdef PART_BOOT
60026165e63Sdholland 		    || ptn == PART_BOOT
60126165e63Sdholland #endif
60226165e63Sdholland 		    || ptn == PART_C) {
60326165e63Sdholland 			m->opt_flags = OPT_IGNORE;
60426165e63Sdholland 		} else {
60526165e63Sdholland 			m->opt_flags = 0;
606da5a563bSmartin 			if (pm->bsdlabel[ptn].pi_fstype == FS_UNUSED)
60726165e63Sdholland 				continue;
60826165e63Sdholland 		}
60926165e63Sdholland 		show_unused_ptn = ptn + 2;
61026165e63Sdholland 	}
61126165e63Sdholland 
61226165e63Sdholland 	if (!(pi->flags & PIF_SHOW_UNUSED) && ptn > show_unused_ptn) {
61326165e63Sdholland 		ptn = show_unused_ptn;
61426165e63Sdholland 		m = &menu->opts[ptn];
61526165e63Sdholland 		m->opt_name = MSG_show_all_unused_partitions;
61626165e63Sdholland 		m->opt_action = show_all_unused;
61726165e63Sdholland 		ptn++;
61826165e63Sdholland 	}
61926165e63Sdholland 
62026165e63Sdholland 	m = &menu->opts[ptn];
62126165e63Sdholland 	m->opt_menu = MENU_sizechoice;
62226165e63Sdholland 	m->opt_flags = OPT_SUB;
62326165e63Sdholland 	m->opt_action = NULL;
62426165e63Sdholland 	m->opt_name = MSG_askunits;
62526165e63Sdholland 
62626165e63Sdholland 	menu->numopts = ptn + 1;
62726165e63Sdholland }
62826165e63Sdholland 
62926165e63Sdholland /*
63026165e63Sdholland  * Check a disklabel.
63126165e63Sdholland  * If there are overlapping active partitions,
63226165e63Sdholland  * Ask the user if they want to edit the partition or give up.
63326165e63Sdholland  */
63426165e63Sdholland int
63526165e63Sdholland edit_and_check_label(partinfo *lp, int nparts, int rawpart, int bsdpart)
63626165e63Sdholland {
63726165e63Sdholland 	static struct menu_ent *menu;
63826165e63Sdholland 	static int menu_no = -1;
63926165e63Sdholland 	static struct ptn_menu_info pi;
64026165e63Sdholland 	int maxpart = getmaxpartitions();
64126165e63Sdholland 
64226165e63Sdholland 	if (menu == NULL) {
64326165e63Sdholland 		menu = malloc((maxpart + 1) * sizeof *menu);
64426165e63Sdholland 		if (!menu)
64526165e63Sdholland 			return 1;
64626165e63Sdholland 	}
64726165e63Sdholland 
64826165e63Sdholland 	if (menu_no == -1) {
64926165e63Sdholland 		menu_no = new_menu(NULL, menu, maxpart + 1,
65026165e63Sdholland 			0, -1, maxpart + 2, 74,
65126165e63Sdholland 			MC_ALWAYS_SCROLL | MC_NOBOX | MC_DFLTEXIT,
65226165e63Sdholland 			set_label_texts, fmt_fspart, NULL, NULL,
65326165e63Sdholland 			MSG_partition_sizes_ok);
65426165e63Sdholland 	}
65526165e63Sdholland 
65626165e63Sdholland 	if (menu_no < 0)
65726165e63Sdholland 		return 1;
65826165e63Sdholland 
65926165e63Sdholland 	pi.flags = 0;
660da5a563bSmartin 	pm->current_cylsize = pm->dlcylsize;
66126165e63Sdholland 
66226165e63Sdholland 	for (;;) {
66326165e63Sdholland 		/* first give the user the option to edit the label... */
66426165e63Sdholland 		process_menu(menu_no, &pi);
66526165e63Sdholland 
66626165e63Sdholland 		/* User thinks the label is OK. */
66726165e63Sdholland 		/* check we have a single root fs */
668da5a563bSmartin 		if (check_one_root(lp, nparts) == 0 && partman_go == 0)
66926165e63Sdholland 			msg_display(MSG_must_be_one_root);
67026165e63Sdholland 		else
67126165e63Sdholland 			/* Check for overlaps */
672da5a563bSmartin 			if (checkoverlap(lp, nparts, rawpart, bsdpart) == 0)
67326165e63Sdholland 				return 1;
67426165e63Sdholland 
67526165e63Sdholland 		/*XXX ???*/
67626165e63Sdholland 		msg_display_add(MSG_edit_partitions_again);
67786ffd738Smartin 		if (!ask_yesno(NULL))
67826165e63Sdholland 			return(0);
67926165e63Sdholland 	}
68026165e63Sdholland 
68126165e63Sdholland 	/*NOTREACHED*/
68226165e63Sdholland }
68326165e63Sdholland 
68426165e63Sdholland /*
68526165e63Sdholland  * Read a label from disk into a sysinst label structure.
68626165e63Sdholland  */
68726165e63Sdholland int
68826165e63Sdholland incorelabel(const char *dkname, partinfo *lp)
68926165e63Sdholland {
69026165e63Sdholland 	struct disklabel lab;
69126165e63Sdholland 	int i, maxpart;
69226165e63Sdholland 	struct partition *pp;
69326165e63Sdholland 	int fd;
69426165e63Sdholland 	char buf[64];
69526165e63Sdholland 
69626165e63Sdholland 	if (get_real_geom(dkname, &lab) == 0)
69726165e63Sdholland 		return -1;
69826165e63Sdholland 
69926165e63Sdholland 	touchwin(stdscr);
70026165e63Sdholland 	maxpart = getmaxpartitions();
70126165e63Sdholland 	if (maxpart > MAXPARTITIONS)
70226165e63Sdholland 		maxpart = MAXPARTITIONS;
70326165e63Sdholland 	if (maxpart > lab.d_npartitions)
70426165e63Sdholland 		maxpart = lab.d_npartitions;
70526165e63Sdholland 
70626165e63Sdholland 	/*
70726165e63Sdholland 	 * Historically sysinst writes the name to d_typename rather
70826165e63Sdholland 	 * than d_diskname.  Who knows why, but pull the value back here.
70926165e63Sdholland 	 */
71026165e63Sdholland 	if (lab.d_typename[0] != 0 && strcmp(lab.d_typename, "unknown") != 0)
711da5a563bSmartin 		strlcpy(pm->bsddiskname, lab.d_typename, sizeof pm->bsddiskname);
71226165e63Sdholland 
71326165e63Sdholland 	fd = opendisk(dkname, O_RDONLY, buf, sizeof buf, 0);
71426165e63Sdholland 	pp = &lab.d_partitions[0];
71526165e63Sdholland 	for (i = 0; i < maxpart; lp++, pp++, i++) {
71626165e63Sdholland 		lp->pi_partition = *pp;
71726165e63Sdholland 		if (lp->pi_fstype >= FSMAXTYPES)
71826165e63Sdholland 			lp->pi_fstype = FS_OTHER;
71926165e63Sdholland 		strlcpy(lp->pi_mount, get_last_mounted(fd, pp->p_offset, lp),
72026165e63Sdholland 			sizeof lp->pi_mount);
72126165e63Sdholland 	}
72226165e63Sdholland 	if (fd != -1)
72326165e63Sdholland 		close(fd);
72426165e63Sdholland 
72526165e63Sdholland 	return 0;
72626165e63Sdholland }
72726165e63Sdholland 
72826165e63Sdholland /*
72926165e63Sdholland  * Try to get 'last mounted on' (or equiv) from fs superblock.
73026165e63Sdholland  */
73126165e63Sdholland const char *
73226165e63Sdholland get_last_mounted(int fd, int partstart, partinfo *lp)
73326165e63Sdholland {
73426165e63Sdholland 	static char sblk[SBLOCKSIZE];		/* is this enough? */
73526165e63Sdholland 	struct fs *SB = (struct fs *)sblk;
73626165e63Sdholland 	static const int sblocks[] = SBLOCKSEARCH;
73726165e63Sdholland 	const int *sbp;
73826165e63Sdholland 	char *cp;
73926165e63Sdholland 	const char *mnt = NULL;
74026165e63Sdholland 	int len;
74126165e63Sdholland 
74226165e63Sdholland 	if (fd == -1)
74326165e63Sdholland 		return "";
74426165e63Sdholland 
74526165e63Sdholland 	/* Check UFS1/2 (and hence LFS) superblock */
74626165e63Sdholland 	for (sbp = sblocks; mnt == NULL && *sbp != -1; sbp++) {
74726165e63Sdholland 		if (pread(fd, sblk, sizeof sblk,
74826165e63Sdholland 		    partstart * (off_t)512 + *sbp) != sizeof sblk)
74926165e63Sdholland 			continue;
75026165e63Sdholland 		/* Maybe we should validate the checksum??? */
75126165e63Sdholland 		switch (SB->fs_magic) {
75226165e63Sdholland 		case FS_UFS1_MAGIC:
75326165e63Sdholland 		case FS_UFS1_MAGIC_SWAPPED:
75426165e63Sdholland 			if (!(SB->fs_old_flags & FS_FLAGS_UPDATED)) {
75526165e63Sdholland 				if (*sbp == SBLOCK_UFS1)
75626165e63Sdholland 					mnt = (const char *)SB->fs_fsmnt;
75726165e63Sdholland 			} else {
75826165e63Sdholland 				/* Check we have the main superblock */
75926165e63Sdholland 				if (SB->fs_sblockloc == *sbp)
76026165e63Sdholland 					mnt = (const char *)SB->fs_fsmnt;
76126165e63Sdholland 			}
76226165e63Sdholland 			continue;
76326165e63Sdholland 		case FS_UFS2_MAGIC:
76426165e63Sdholland 		case FS_UFS2_MAGIC_SWAPPED:
76526165e63Sdholland 			/* Check we have the main superblock */
76626165e63Sdholland 			if (SB->fs_sblockloc == *sbp) {
76726165e63Sdholland 				mnt = (const char *)SB->fs_fsmnt;
76826165e63Sdholland 				if (lp != NULL)
76926165e63Sdholland 					lp->pi_flags |= PIF_FFSv2;
77026165e63Sdholland 			}
77126165e63Sdholland 			continue;
77226165e63Sdholland 		}
77326165e63Sdholland 
77426165e63Sdholland #if 0	/* Requires fs/ext2fs/ext2fs.h which collides badly... */
77526165e63Sdholland 		if ((struct ext2fs *)sblk)->e2fs_magic == E2FS_MAGIC) {
77626165e63Sdholland 			mnt = ((struct ext2fs *)sblk)->e2fs_fsmnt;
77726165e63Sdholland 			continue;
77826165e63Sdholland 		}
77926165e63Sdholland #endif
78026165e63Sdholland 		if (*sbp != 0)
78126165e63Sdholland 			continue;
78226165e63Sdholland 
78326165e63Sdholland 		/* If start of partition check for other fs types */
78426165e63Sdholland 		if (sblk[0x42] == 0x29 && memcmp(sblk + 0x52, "FAT", 3) == 0) {
78526165e63Sdholland 			/* Probably a FAT filesystem, report volume name */
78626165e63Sdholland 			cp = strchr(sblk + 0x47, ' ');
78726165e63Sdholland 			if (cp == NULL || cp - (sblk + 0x47) > 11)
78826165e63Sdholland 				cp = sblk + 0x47 + 11;
78926165e63Sdholland 			*cp = 0;
79026165e63Sdholland 			return sblk + 0x47;
79126165e63Sdholland 		}
79226165e63Sdholland 	}
79326165e63Sdholland 
79426165e63Sdholland 	if (mnt == NULL)
79526165e63Sdholland 		return "";
79626165e63Sdholland 
79726165e63Sdholland 	/* If sysinst mounted this last then strip prefix */
79826165e63Sdholland 	len = strlen(targetroot_mnt);
79926165e63Sdholland 	if (memcmp(mnt, targetroot_mnt, len) == 0) {
80026165e63Sdholland 		if (mnt[len] == 0)
80126165e63Sdholland 			return "/";
80226165e63Sdholland 		if (mnt[len] == '/')
80326165e63Sdholland 			return mnt + len;
80426165e63Sdholland 	}
80526165e63Sdholland 	return mnt;
80626165e63Sdholland 	#undef SB
80726165e63Sdholland }
80826165e63Sdholland 
80926165e63Sdholland /* Ask for a partition offset, check bounds and do the needed roundups */
81026165e63Sdholland static uint32_t
81126165e63Sdholland getpartoff(uint32_t defpartstart)
81226165e63Sdholland {
81326165e63Sdholland 	char defsize[20], isize[20], maxpartc;
81426165e63Sdholland 	uint32_t i;
81526165e63Sdholland 	uint32_t localsizemult;
81626165e63Sdholland 	int partn;
81726165e63Sdholland 	const char *errmsg = "\n";
81826165e63Sdholland 
81926165e63Sdholland 	maxpartc = 'a' + getmaxpartitions() - 1;
82026165e63Sdholland 	for (;;) {
82126165e63Sdholland 		snprintf(defsize, sizeof defsize, "%d", defpartstart/sizemult);
82226165e63Sdholland 		msg_prompt_win(MSG_label_offset, -1, 13, 70, 9,
82326165e63Sdholland 		    (defpartstart > 0) ? defsize : NULL, isize, sizeof isize,
82426165e63Sdholland 		    errmsg, maxpartc, maxpartc, multname);
82526165e63Sdholland 		if (strcmp(defsize, isize) == 0)
82626165e63Sdholland 			/* Don't do rounding if default accepted */
82726165e63Sdholland 			return defpartstart;
82826165e63Sdholland 		if (isize[1] == '\0' && isize[0] >= 'a' &&
82926165e63Sdholland 		    isize[0] <= maxpartc) {
83026165e63Sdholland 			partn = isize[0] - 'a';
831da5a563bSmartin 			i = pm->bsdlabel[partn].pi_size + pm->bsdlabel[partn].pi_offset;
83226165e63Sdholland 			localsizemult = 1;
83326165e63Sdholland 		} else if (atoi(isize) == -1) {
834da5a563bSmartin 			i = pm->ptstart;
83526165e63Sdholland 			localsizemult = 1;
83626165e63Sdholland 		} else {
83726165e63Sdholland 			if (atofsb(isize, &i, &localsizemult)) {
83826165e63Sdholland 				errmsg = msg_string(MSG_invalid_sector_number);
83926165e63Sdholland 				continue;
84026165e63Sdholland 			}
84126165e63Sdholland 		}
84226165e63Sdholland 		/* round to cylinder size if localsizemult != 1 */
843da5a563bSmartin 		i = NUMSEC(i/localsizemult, localsizemult, pm->dlcylsize);
84426165e63Sdholland 		/* Adjust to start of slice if needed */
845da5a563bSmartin 		if ((i < pm->ptstart && (pm->ptstart - i) < localsizemult) ||
846da5a563bSmartin 		    (i > pm->ptstart && (i - pm->ptstart) < localsizemult)) {
847da5a563bSmartin 			i = pm->ptstart;
84826165e63Sdholland 		}
849da5a563bSmartin 		if (i <= pm->dlsize)
85026165e63Sdholland 			break;
85126165e63Sdholland 		errmsg = msg_string(MSG_startoutsidedisk);
85226165e63Sdholland 	}
85326165e63Sdholland 	return i;
85426165e63Sdholland }
85526165e63Sdholland 
85626165e63Sdholland 
85726165e63Sdholland /* Ask for a partition size, check bounds and do the needed roundups */
85826165e63Sdholland static uint32_t
85926165e63Sdholland getpartsize(uint32_t partstart, uint32_t defpartsize)
86026165e63Sdholland {
86126165e63Sdholland 	char dsize[20], isize[20], maxpartc;
86226165e63Sdholland 	const char *errmsg = "\n";
86326165e63Sdholland 	uint32_t i, partend, localsizemult;
864da5a563bSmartin 	uint32_t fsptend = pm->ptstart + pm->ptsize;
86526165e63Sdholland 	int partn;
86626165e63Sdholland 
86726165e63Sdholland 	maxpartc = 'a' + getmaxpartitions() - 1;
86826165e63Sdholland 	for (;;) {
86926165e63Sdholland 		snprintf(dsize, sizeof dsize, "%d", defpartsize/sizemult);
87026165e63Sdholland 		msg_prompt_win(MSG_label_size, -1, 12, 70, 9,
87126165e63Sdholland 		    (defpartsize != 0) ? dsize : 0, isize, sizeof isize,
87226165e63Sdholland 		    errmsg, maxpartc, multname);
87326165e63Sdholland 		if (strcmp(isize, dsize) == 0)
87426165e63Sdholland 			return defpartsize;
87526165e63Sdholland 		if (isize[1] == '\0' && isize[0] >= 'a' &&
87626165e63Sdholland 		    isize[0] <= maxpartc) {
87726165e63Sdholland 			partn = isize[0] - 'a';
878da5a563bSmartin 			i = pm->bsdlabel[partn].pi_offset - partstart;
87926165e63Sdholland 			localsizemult = 1;
88026165e63Sdholland 		} else if (atoi(isize) == -1) {
88126165e63Sdholland 			i = fsptend - partstart;
88226165e63Sdholland 			localsizemult = 1;
88326165e63Sdholland 		} else {
88426165e63Sdholland 			if (atofsb(isize, &i, &localsizemult)) {
88526165e63Sdholland 				errmsg = msg_string(MSG_invalid_sector_number);
88626165e63Sdholland 				continue;
88726165e63Sdholland 			}
88826165e63Sdholland 		}
88926165e63Sdholland 		/*
89026165e63Sdholland 		 * partend is aligned to a cylinder if localsizemult
89126165e63Sdholland 		 * is not 1 sector
89226165e63Sdholland 		 */
89326165e63Sdholland 		partend = NUMSEC((partstart + i) / localsizemult,
894da5a563bSmartin 		    localsizemult, pm->dlcylsize);
89526165e63Sdholland 		/* Align to end-of-disk or end-of-slice if close enough */
896da5a563bSmartin 		if (partend > (pm->dlsize - localsizemult)
897da5a563bSmartin 		    && partend < (pm->dlsize + localsizemult))
898da5a563bSmartin 			partend = pm->dlsize;
89926165e63Sdholland 		if (partend > (fsptend - localsizemult)
90026165e63Sdholland 		    && partend < (fsptend + localsizemult))
90126165e63Sdholland 			partend = fsptend;
90226165e63Sdholland 		/* sanity checks */
903da5a563bSmartin 		if (partend > pm->dlsize) {
904da5a563bSmartin 			partend = pm->dlsize;
90526165e63Sdholland 			msg_prompt_win(MSG_endoutsidedisk, -1, 13, 70, 6,
90626165e63Sdholland 			    NULL, isize, 1,
90726165e63Sdholland 			    (partend - partstart) / sizemult, multname);
90826165e63Sdholland 		}
90926165e63Sdholland 		if (partend < partstart)
91026165e63Sdholland 			return 0;
91126165e63Sdholland 		return (partend - partstart);
91226165e63Sdholland 	}
91326165e63Sdholland 	/* NOTREACHED */
91426165e63Sdholland }
91526165e63Sdholland 
91626165e63Sdholland /*
91726165e63Sdholland  * convert a string to a number of sectors, with a possible unit
91826165e63Sdholland  * 150M = 150 Megabytes
91926165e63Sdholland  * 2000c = 2000 cylinders
92026165e63Sdholland  * 150256s = 150256 sectors
92126165e63Sdholland  * Without units, use the default (sizemult)
92226165e63Sdholland  * returns the number of sectors, and the unit used (for roundups).
92326165e63Sdholland  */
92426165e63Sdholland 
92526165e63Sdholland static int
92626165e63Sdholland atofsb(const char *str, uint32_t *p_val, uint32_t *localsizemult)
92726165e63Sdholland {
92826165e63Sdholland 	int i;
92926165e63Sdholland 	uint32_t val;
93026165e63Sdholland 
93126165e63Sdholland 	*localsizemult = sizemult;
93226165e63Sdholland 	if (str[0] == '\0') {
93326165e63Sdholland 		return 1;
93426165e63Sdholland 	}
93526165e63Sdholland 	val = 0;
93626165e63Sdholland 	for (i = 0; str[i] != '\0'; i++) {
93726165e63Sdholland 		if (str[i] >= '0' && str[i] <= '9') {
93826165e63Sdholland 			val = val * 10 + str[i] - '0';
93926165e63Sdholland 			continue;
94026165e63Sdholland 		}
94126165e63Sdholland 		if (str[i + 1] != '\0') {
94226165e63Sdholland 			/* A non-digit caracter, not at the end */
94326165e63Sdholland 			return 1;
94426165e63Sdholland 		}
94526165e63Sdholland 		if (str[i] == 'G' || str[i] == 'g') {
94626165e63Sdholland 			val *= 1024;
947da5a563bSmartin 			*localsizemult = MEG / pm->sectorsize;
94826165e63Sdholland 			break;
94926165e63Sdholland 		}
95026165e63Sdholland 		if (str[i] == 'M' || str[i] == 'm') {
951da5a563bSmartin 			*localsizemult = MEG / pm->sectorsize;
95226165e63Sdholland 			break;
95326165e63Sdholland 		}
95426165e63Sdholland 		if (str[i] == 'c') {
955da5a563bSmartin 			*localsizemult = pm->dlcylsize;
95626165e63Sdholland 			break;
95726165e63Sdholland 		}
95826165e63Sdholland 		if (str[i] == 's') {
95926165e63Sdholland 			*localsizemult = 1;
96026165e63Sdholland 			break;
96126165e63Sdholland 		}
96226165e63Sdholland 		/* not a known unit */
96326165e63Sdholland 		return 1;
96426165e63Sdholland 	}
96526165e63Sdholland 	*p_val = val * (*localsizemult);
96626165e63Sdholland 	return 0;
96726165e63Sdholland }
968