diff options
author | Kjell Wooding <kjell@cvs.openbsd.org> | 2002-01-18 08:33:11 +0000 |
---|---|---|
committer | Kjell Wooding <kjell@cvs.openbsd.org> | 2002-01-18 08:33:11 +0000 |
commit | 4abdd7d2f8cea4f749015419d3966ee70325b5ca (patch) | |
tree | 222f4e30704e6e1066e990b849b1e28d173c7b64 /sbin/fdisk | |
parent | ee68995a525cd46f081c7c744bdb693f23c871a1 (diff) |
Add disklabel-style editing for size/offset values in
the partition tables. These values may now contain units,
such as "300k" "500M" or "2G".
(sectors, bytes, and cylinders are also supported.)
This should largely eliminate the need for a calculator
when using fdisk on large disks.
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 */ |