pp->p_size = ui; if (pp->p_size == 0) return;
editor_add(lp, mp, freep, p)	struct disklabel *lp;	char **mp;	u_int32_t *freep;	char *p;{	struct partition *pp;	struct diskchunk *chunks;	char buf[BUFSIZ];	int i, partno;	u_int32_t ui, old_offset, old_size;	/* XXX - prompt user to steal space from another partition instead */	if (*freep == 0) {		fputs("No space left, you need to shrink a partition\n",		    stderr);		return;	}	/* XXX - make more like other editor_* */	if (p != NULL) {		partno = p[0] - 'a';		if (partno < 0 || partno == 2 || partno >= MAXPARTITIONS) {			fprintf(stderr,			    "Partition must be between 'a' and '%c' "			    "(excluding 'c').\n", 'a' + MAXPARTITIONS - 1);			return;		} else if (lp->d_partitions[partno].p_fstype != FS_UNUSED &&		    lp->d_partitions[partno].p_size != 0) {			fprintf(stderr,			    "Partition '%c' exists.  Delete it first.\n",			    p[0]);			return;		}	} else {		/* Find first unused partition that is not 'c' */		for (partno = 0; partno < MAXPARTITIONS; partno++, p++) {			if (lp->d_partitions[partno].p_size == 0 && partno != 2)				break;		}		if (partno < MAXPARTITIONS) {			buf[0] = partno + 'a';			buf[1] = '\0';			p = &buf[0];		} else			p = NULL;		for (;;) {			p = getstring(lp, "partition",			    "The letter of the new partition, a - p.", p);			if (p == NULL)				return;			partno = p[0] - 'a';			if (lp->d_partitions[partno].p_fstype != FS_UNUSED &&			    lp->d_partitions[partno].p_size != 0) {				fprintf(stderr,				    "Partition '%c' already exists.\n", p[0]);			} else if (partno >= 0 && partno < MAXPARTITIONS)				break;			fprintf(stderr,			    "Partition must be between 'a' and '%c'.\n",			    'a' + MAXPARTITIONS - 1);		}	}	/* Increase d_npartitions if necesary */	if (partno >= lp->d_npartitions)		lp->d_npartitions = partno + 1;	/* Set defaults */	pp = &lp->d_partitions[partno];	if (partno >= lp->d_npartitions)		lp->d_npartitions = partno + 1;	memset(pp, 0, sizeof(*pp));	pp->p_fstype = partno == 1 ? FS_SWAP : FS_BSDFFS;	pp->p_fsize = 1024;	pp->p_frag = 8;	pp->p_cpg = 16;	pp->p_size = *freep;	pp->p_offset = next_offset(lp, pp);	/* must be computed last */#if NUMBOOT == 1	/* Don't clobber boot blocks */	if (pp->p_offset == 0) {		pp->p_offset = lp->d_secpercyl;		pp->p_size -= lp->d_secpercyl;	}#endif	old_offset = pp->p_offset;	old_size = pp->p_size;getoff1:	/* Get offset */	for (;;) {		ui = getuint(lp, partno, "offset",		   "Starting sector for this partition.", pp->p_offset,		   pp->p_offset, 0, DO_CONVERSIONS |		   (pp->p_fstype == FS_BSDFFS ? DO_ROUNDING : 0));		if (ui == UINT_MAX - 1) {			fputs("Command aborted\n", stderr);			pp->p_size = 0;		/* effective delete */			return;		} else if (ui == UINT_MAX)			fputs("Invalid entry\n", stderr);		else if (ui < starting_sector)			fprintf(stderr, "The OpenBSD portion of the disk starts"			    " at sector %u, you tried to add a partition at %u."			    "  You can use the 'b' command to change the size "			    "of the OpenBSD portion.\n" , starting_sector, ui);		else if (ui >= ending_sector)			fprintf(stderr, "The OpenBSD portion of the disk ends "			    "at sector %u, you tried to add a partition at %u."			    "  You can use the 'b' command to change the size "			    "of the OpenBSD portion.\n", ending_sector, ui);		else			break;	}	pp->p_offset = ui;	/* Recompute recommended size based on new offset */	ui = pp->p_fstype;	pp->p_fstype = FS_UNUSED;	chunks = free_chunks(lp);	for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {		if (pp->p_offset >= chunks[i].start &&		    pp->p_offset < chunks[i].stop) {			pp->p_size = chunks[i].stop - pp->p_offset;			break;		}	}	pp->p_fstype = ui;		/* Get size */	for (;;) {		ui = getuint(lp, partno, "size", "Size of the partition.",		    pp->p_size, *freep, pp->p_offset, DO_CONVERSIONS |		    ((pp->p_fstype == FS_BSDFFS || pp->p_fstype == FS_SWAP) ?		    DO_ROUNDING : 0));		if (ui == UINT_MAX - 1) {			fputs("Command aborted\n", stderr);			pp->p_size = 0;		/* effective delete */			return;		} else if (ui == UINT_MAX)			fputs("Invalid entry\n", stderr);		else if (ui > *freep)			/* XXX - prompt user to steal space from another partition */			fprintf(stderr,"Sorry, there are only %u sectors left\n",			    *freep);		else if (pp->p_offset + ui > ending_sector)			fprintf(stderr, "The OpenBSD portion of the disk ends "			    "at sector %u, you tried to add a partition ending "			    "at sector %u.  You can use the 'b' command to "			    "change the size of the OpenBSD portion.\n",			    ending_sector, pp->p_offset + ui);		else			break;	}	pp->p_size = ui;	if (pp->p_size == 0)		return;	/* Check for overlap */	if (has_overlap(lp, freep, 0)) {		printf("\nPlease re-enter an offset and size for partition "		    "%c.\n", 'a' + partno);		pp->p_offset = old_offset;		pp->p_size = old_size;		goto getoff1;		/* Yeah, I know... */	}	/* Get fstype */	if (pp->p_fstype < FSMAXTYPES) {		p = getstring(lp, "FS type",		    "Filesystem type (usually 4.2BSD or swap)",		    fstypenames[pp->p_fstype]);		if (p == NULL) {			fputs("Command aborted\n", stderr);			pp->p_size = 0;		/* effective delete */			return;		}		for (i = 0; i < FSMAXTYPES; i++) {			if (!strcasecmp(p, fstypenames[i])) {				pp->p_fstype = i;				break;			}		}		if (i >= FSMAXTYPES) {			printf("Unrecognized filesystem type '%s', treating as 'unknown'\n", p);			pp->p_fstype = FS_OTHER;		}	} else {		for (;;) {			ui = getuint(lp, partno, "FS type (decimal)",			    "Filesystem type as a decimal number; usually 7 (4.2BSD) or 1 (swap).",			    pp->p_fstype, pp->p_fstype, 0, 0);			if (ui == UINT_MAX - 1) {				fputs("Command aborted\n", stderr);				pp->p_size = 0;		/* effective delete */				return;			} if (ui == UINT_MAX)				fputs("Invalid entry\n", stderr);			else				break;		}		pp->p_fstype = ui;	}	if (pp->p_fstype == FS_BSDFFS || pp->p_fstype == FS_UNUSED) {		/* get fsize */		for (;;) {			ui = getuint(lp, partno, "fragment size",			    "Size of fs block fragments.  Usually 1024 or 512.",			    pp->p_fsize, pp->p_fsize, 0, 0);			if (ui == UINT_MAX - 1) {				fputs("Command aborted\n", stderr);				pp->p_size = 0;		/* effective delete */				return;			} else if (ui == UINT_MAX)				fputs("Invalid entry\n", stderr);			else				break;		}		pp->p_fsize = ui;		if (pp->p_fsize == 0)			puts("Zero fragment size implies zero block size");		/* get bsize */		/* XXX - do before frag size? */		for (; pp->p_fsize > 0;) {			ui = getuint(lp, partno, "block size",			    "Size of filesystem blocks.  Usually 8192 or 4096.",			    pp->p_fsize * pp->p_frag, pp->p_fsize * pp->p_frag,			    0, 0);			/* sanity checks */			if (ui == UINT_MAX - 1) {				fputs("Command aborted\n", stderr);				pp->p_size = 0;		/* effective delete */				return;			} else if (ui == UINT_MAX)				fputs("Invalid entry\n", stderr);			else if (ui < getpagesize())				fprintf(stderr,				    "Error: block size must be at least as big "				    "as page size (%d).\n", getpagesize());			else if (ui % pp->p_fsize != 0)				fputs("Error: block size must be a multiple of the fragment size.\n", stderr);			else if (ui / pp->p_fsize < 1)				fputs("Error: block size must be at least as big as fragment size.\n", stderr);			else				break;		}		pp->p_frag = ui / pp->p_fsize;		if (pp->p_fstype == FS_BSDFFS) {			/* get cpg */			for (;;) {				ui = getuint(lp, partno, "cpg",				    "Number of filesystem cylinders per group.  Usually 16 or 8.",				    pp->p_cpg, pp->p_cpg, 0, 0);				if (ui == UINT_MAX - 1) {					fputs("Command aborted\n", stderr);					pp->p_size = 0;	/* effective delete */					return;				} else if (ui == UINT_MAX)					fputs("Invalid entry\n", stderr);				else					break;			}			pp->p_cpg = ui;		}		if (mp != NULL && pp->p_fstype != FS_UNUSED &&		    pp->p_fstype != FS_SWAP && pp->p_fstype != FS_BOOT &&		    pp->p_fstype != FS_OTHER) {			/* get mount point */			p = getstring(lp, "mount point",			    "Where to mount this filesystem (ie: / /var /usr)",			    "none");			if (p == NULL) {				fputs("Command aborted\n", stderr);				pp->p_size = 0;		/* effective delete */				return;			}			if (strcasecmp(p, "none") != 0) {				/* XXX - check that it starts with '/' */				if (mp[partno] != NULL)					free(mp[partno]);				if ((mp[partno] = strdup(p)) == NULL)					errx(4, "out of memory");			}		}	}	/* Update free sector count and make sure things stay contiguous. */	*freep -= pp->p_size;	if (pp->p_size + pp->p_offset > ending_sector ||	    has_overlap(lp, freep, -1))		make_contiguous(lp);}