summaryrefslogtreecommitdiff
path: root/sbin/fdisk
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/fdisk')
-rw-r--r--sbin/fdisk/cmd.c15
-rw-r--r--sbin/fdisk/misc.c138
-rw-r--r--sbin/fdisk/misc.h5
3 files changed, 151 insertions, 7 deletions
diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c
index 470b0128a98..2781adbaae9 100644
--- a/sbin/fdisk/cmd.c
+++ b/sbin/fdisk/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.28 2001/01/28 00:56:07 weingart Exp $ */
+/* $OpenBSD: cmd.c,v 1.29 2002/01/18 08:33:10 kjell Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -175,15 +175,20 @@ Xedit(cmd, disk, mbr, tt, offset)
u_int m;
/* Get data */
- EDIT("Partition offset", ASK_DEC, pp->bs, 0,
- disk->real->size, NULL);
+ pp->bs = getuint(disk, "offset",
+ "Starting sector for this partition.", pp->bs,
+ disk->real->size, 0, DO_CONVERSIONS |
+ (pp->id == FS_BSDFFS ? DO_ROUNDING : 0));
+
m = MAX(pp->ns, disk->real->size - pp->bs);
if ( m > disk->real->size - pp->bs) {
/* dont have default value extend beyond end of disk */
m = disk->real->size - pp->bs;
}
- EDIT("Partition size", ASK_DEC, pp->ns, 1,
- m, NULL);
+ pp->ns = getuint(disk, "size", "Size of the partition.",
+ pp->ns, m, pp->bs , DO_CONVERSIONS |
+ ((pp->id == FS_BSDFFS || pp->id == FS_SWAP) ?
+ DO_ROUNDING : 0));
/* Fix up CHS values */
PRT_fix_CHS(disk, pp, pn);
diff --git a/sbin/fdisk/misc.c b/sbin/fdisk/misc.c
index 6941547c447..e731194cb3b 100644
--- a/sbin/fdisk/misc.c
+++ b/sbin/fdisk/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.6 1997/10/19 23:30:48 deraadt Exp $ */
+/* $OpenBSD: misc.c,v 1.7 2002/01/18 08:33:10 kjell Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -35,7 +35,9 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <sys/disklabel.h>
+#include <machine/limits.h>
#include "misc.h"
@@ -171,3 +173,137 @@ putlong(p, l)
*cp++ = l >> 16;
*cp++ = l >> 24;
}
+
+/*
+ * adapted from sbin/disklabel/editor.c
+ * Returns UINT_MAX on error
+ */
+u_int32_t
+getuint(disk, prompt, helpstring, oval, maxval, offset, flags)
+ disk_t *disk;
+ char *prompt;
+ char *helpstring;
+ u_int32_t oval;
+ u_int32_t maxval;
+ u_int32_t offset;
+ int flags;
+{
+ char buf[BUFSIZ], *endptr, *p, operator = '\0';
+ u_int32_t rval = oval;
+ size_t n;
+ int mult = 1;
+ double d;
+ int secpercyl;
+
+ secpercyl = disk->real->sectors * disk->real->heads;
+
+ /* We only care about the remainder */
+ offset = offset % secpercyl;
+
+ buf[0] = '\0';
+ do {
+ printf("%s: [%u] ", prompt, oval);
+ if (fgets(buf, sizeof(buf), stdin) == NULL) {
+ buf[0] = '\0';
+ if (feof(stdin)) {
+ clearerr(stdin);
+ putchar('\n');
+ return(UINT_MAX - 1);
+ }
+ }
+ n = strlen(buf);
+ if (n > 0 && buf[n-1] == '\n')
+ buf[--n] = '\0';
+ if (buf[0] == '?')
+ puts(helpstring);
+ } while (buf[0] == '?');
+
+ if (buf[0] == '*' && buf[1] == '\0') {
+ rval = maxval;
+ } else {
+ /* deal with units */
+ if (buf[0] != '\0' && n > 0) {
+ if ((flags & DO_CONVERSIONS)) {
+ switch (tolower(buf[n-1])) {
+
+ case 'c':
+ mult = secpercyl;
+ buf[--n] = '\0';
+ break;
+ case 'b':
+ mult = -DEV_BSIZE;
+ buf[--n] = '\0';
+ break;
+ case 's':
+ buf[--n] = '\0';
+ break;
+ case 'k':
+ mult = 1024 / DEV_BSIZE;
+ buf[--n] = '\0';
+ break;
+ case 'm':
+ mult = 1048576 / DEV_BSIZE;
+ buf[--n] = '\0';
+ break;
+ case 'g':
+ mult = 1073741824 / DEV_BSIZE;
+ buf[--n] = '\0';
+ break;
+ }
+ }
+
+ /* Did they give us an operator? */
+ p = &buf[0];
+ if (*p == '+' || *p == '-')
+ operator = *p++;
+
+ endptr = p;
+ errno = 0;
+ d = strtod(p, &endptr);
+ if (errno == ERANGE)
+ rval = UINT_MAX; /* too big/small */
+ else if (*endptr != '\0') {
+ errno = EINVAL; /* non-numbers in str */
+ rval = UINT_MAX;
+ } else {
+ /* XXX - should check for overflow */
+ if (mult > 0)
+ rval = d * mult;
+ else
+ /* Negative mult means divide (fancy) */
+ rval = d / (-mult);
+
+ /* Apply the operator */
+ if (operator == '+')
+ rval += oval;
+ else if (operator == '-')
+ rval = oval - rval;
+ }
+ }
+ }
+ if ((flags & DO_ROUNDING) && rval < UINT_MAX) {
+#ifndef CYLCHECK
+ /* Round to nearest cylinder unless given in sectors */
+ if (mult != 1)
+#endif
+ {
+ u_int32_t cyls;
+
+ /* If we round up past the end, round down instead */
+ cyls = (u_int32_t)((rval / (double)secpercyl)
+ + 0.5);
+ if (cyls != 0 && secpercyl != 0) {
+ if ((cyls * secpercyl) - offset > maxval)
+ cyls--;
+
+ if (rval != (cyls * secpercyl) - offset) {
+ rval = (cyls * secpercyl) - offset;
+ printf("Rounding to nearest cylinder: %u\n",
+ rval);
+ }
+ }
+ }
+ }
+
+ return(rval);
+}
diff --git a/sbin/fdisk/misc.h b/sbin/fdisk/misc.h
index 7d4e386a83b..92e82e83a42 100644
--- a/sbin/fdisk/misc.h
+++ b/sbin/fdisk/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.4 2001/08/12 12:03:01 heko Exp $ */
+/* $OpenBSD: misc.h,v 1.5 2002/01/18 08:33:10 kjell Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -39,6 +39,8 @@
/* Constants */
#define ASK_HEX 0x01
#define ASK_DEC 0x02
+#define DO_CONVERSIONS 0x00000001
+#define DO_ROUNDING 0x00000002
/* Prototypes */
int ask_cmd __P((cmd_t *));
@@ -48,6 +50,7 @@ u_int16_t getshort __P((void *));
u_int32_t getlong __P((void *));
void putshort __P((void *, u_int16_t));
void putlong __P((void *, u_int32_t));
+u_int32_t getuint __P((disk_t *, char *, char *, u_int32_t, u_int32_t, u_int32_t, int));
#endif /* _MISC_H */