diff options
Diffstat (limited to 'sbin/fdisk')
-rw-r--r-- | sbin/fdisk/cmd.c | 15 | ||||
-rw-r--r-- | sbin/fdisk/misc.c | 138 | ||||
-rw-r--r-- | sbin/fdisk/misc.h | 5 |
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 */ |