tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Making fdisk accept percentages (and modifiers on shell)
Hi,
it might be useful (and specially IS, for me ;) to have fdisk specify
percentages instead of absolute size values.
Thus, the attached patches do exactly that, and they also extend the current
modifiers (MB, GB, cyl) to batch-mode (-s). Then, TB was added (though
unnecessary, but you don't have to use four digit GB sizes).
Any comments about that?
Regards, Julian
--- sbin/fdisk/fdisk.8
+++ sbin/fdisk/fdisk.8
@@ -308,10 +308,11 @@
.Ar size ,
and optionally
.Ar bootmenu .
This flag requires the use of a partition selection flag
.Pq Fl 0 , 1 , 2 , 3 , No or Fl E Ar number .
+.Pp
.It Fl T Ar disktype
Use the disklabel
.Ar disktype
instead of the disklabel on
.Ar device .
@@ -339,11 +340,12 @@
and
.Em size
can be specified in blocks (NN),
cylinders (NNc or NNcyl),
megabytes (NNm or NNMB),
-or gigabytes (NNg or NNGB), values in megabytes and gigabytes
+gigabytes (NNg or NNGB)
+or terabytes (NNt or NNTB) values in megabytes and gigabytes
will be rounded to the nearest cylinder boundary.
The
.Em size
may be specified as
.Em $
@@ -553,10 +555,16 @@
from the partition might fail.
.Nx
partitions may be made bootable using
.Xr installboot 8 .
.Sh NOTES
+You can modify the start and size values of partitions in interactive and
+in batch-mode by
+.Em tb , t , gb , g , mb , m , cyl , % ,
+specifying the number to be counted either in terabytes, gigabytes,
+megabytes, cylinders or percentage of the whole disk size.
+.Pp
This program is only available (and useful) on systems with PC-platform-style
MBR partitioning.
.Pp
Traditionally the partition boundaries should be on cylinder boundaries
using the BIOS geometry, with the exception of the first partition,
--- sbin/fdisk/fdisk.c
+++ sbin/fdisk/fdisk.c
@@ -271,10 +271,12 @@
static void get_ptn_alignmemt(void);
#if defined(USE_DISKLIST)
static void get_diskname(const char *, char *, size_t);
#endif
static int change_part(int, int, int, daddr_t, daddr_t, char *);
+static void parse_partstr(char *, int *, daddr_t *, daddr_t *, char **);
+static int64_t parse_smodifier(const char *, int);
static void print_geometry(void);
static int first_active(void);
static void change_active(int);
static void change_bios_geometry(void);
static void dos(int, unsigned char *, unsigned char *, unsigned char *);
@@ -291,10 +293,11 @@
#define DEC_SEC 1 /* asking for a sector number */
#define DEC_RND 2 /* round to end of first track
*/
#define DEC_RND_0 4 /* convert 0 to size of a track
*/
#define DEC_RND_DOWN 8 /* subtract 1 track */
#define DEC_RND_DOWN_2 16 /* subtract 2 tracks */
+#define DEC_RND_BNDY 32 /* round _down_ to boundary, instead of
up. */
static int ptn_id(const char *, int *);
static int type_match(const void *, const void *);
static const char *get_type(int);
static int get_mapping(int, unsigned int *, unsigned int *, unsigned int
*, unsigned long *);
#ifdef BOOTSEL
@@ -329,18 +332,19 @@
{
struct stat sb;
int ch;
size_t len;
char *cp;
+ static char *partstr;
int n;
#ifdef BOOTSEL
daddr_t default_ptn; /* start sector of default ptn */
char *cbootmenu = 0;
#endif
int csysid; /* For the s_flag. */
- unsigned int cstart, csize;
+ daddr_t cstart, csize;
a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
i_flag = B_flag = 0;
v_flag = 0;
E_flag = 0;
csysid = cstart = csize = 0;
@@ -398,22 +402,13 @@
case 'v': /* Be verbose */
v_flag++;
break;
case 's': /* Partition details */
s_flag = 1;
- if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart,
- &csize, &n) == 3) {
- if (optarg[n] == 0)
- break;
-#ifdef BOOTSEL
- if (optarg[n] == '/') {
- cbootmenu = optarg + n + 1;
- break;
- }
-#endif
- }
- errx(1, "Bad argument to the -s flag.");
+ partstr = strdup(optarg);
+ if (!partstr)
+ err(1, "Could not allocate string.");
break;
case 'b': /* BIOS geometry */
b_flag = 1;
if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head,
&b_sec, &n) != 3 || optarg[n] != 0)
@@ -528,13 +523,21 @@
/* Do the update stuff! */
if (u_flag) {
if (!f_flag && !b_flag)
change_bios_geometry();
- if (s_flag)
+ if (s_flag) {
+ parse_partstr(partstr, &csysid, &cstart, &csize,
&cbootmenu);
+#ifndef BOOTSEL
+ if (strlen(cbootmenu))
+ errx(1, "Bad argument to the -s flag: Too many
slashes.");
+#endif
+ free(partstr);
+
change_part(E_flag, partition, csysid, cstart, csize,
cbootmenu);
+ }
else {
int part = partition, chg_ext = E_flag, prompt = 1;
do {
if (prompt) {
printf("\n");
@@ -1955,10 +1958,119 @@
}
}
return 0;
}
+/* This function has the same flags as the other round-determining stuff, but
+ * one with a special meaning: DEC_RND_DOWN rounds also to the lower alignment
+ * boundary, instead of the upper one.
+ * We need this to have a total value of 100%. */
+static int64_t
+parse_smodifier(const char *sizestr, int flags)
+{
+ char *cp;
+ int64_t acc;
+ int valid;
+ int len;
+
+ if (!isdigit((unsigned char)*sizestr))
+ return -1;
+
+ acc = strtoll(sizestr, &cp, 10);
+ len = strcspn(cp, " \t\n");
+ valid = 0;
+ if (len != 0) {
+ if (!strncasecmp(cp, "tb", len)) {
+ acc *= 1024;
+ valid = 1;
+ }
+ if (valid || !strncasecmp(cp, "gb", len)) {
+ acc *= 1024;
+ valid = 1;
+ }
+ if (valid || !strncasecmp(cp, "mb", len)) {
+ acc *= SEC_IN_1M;
+ /* round to whole number of cylinders */
+ acc += ptn_alignment / 2;
+ acc /= ptn_alignment;
+ valid = 1;
+ } else if (!strcmp(cp, "%")) {
+ if (acc < 0 || acc > 100)
+ return -1;
+ acc = disksectors / 100 * acc;
+ /* round to whole number of cylinders */
+ if (acc <= ptn_alignment / 2)
+ acc += ptn_alignment / 2;
+ else if (flags & DEC_RND_DOWN)
+ acc -= ptn_alignment / 2;
+ else
+ acc += ptn_alignment / 2;
+ acc /= ptn_alignment;
+ valid = 1;
+ }
+ if (valid || !strcasecmp(cp, "cyl")) {
+ acc *= ptn_alignment;
+ /* adjustments for cylinder boundary */
+ if (acc == 0 && flags & DEC_RND_0)
+ acc += ptn_0_offset;
+ if (flags & DEC_RND)
+ acc += ptn_0_offset;
+ if (flags & DEC_RND_DOWN)
+ acc -= ptn_0_offset;
+ if (flags & DEC_RND_DOWN_2)
+ acc -= ptn_0_offset;
+ }
+ }
+
+ return acc;
+}
+
+static void
+parse_partstr(char *partstr, int *csysid, daddr_t *cstart,
+ daddr_t *csize, char **cbootmenu)
+{
+ int64_t tval;
+ char *tmpstr;
+
+ /* Get sysid. */
+ tmpstr = strtok(partstr, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ *csysid = strtoll(tmpstr, NULL, 10);
+ if (strspn(tmpstr, "1234567890") != strlen(tmpstr))
+ errx(1, "Bad id argument to the -s flag.");
+
+ /* Get start. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ tval = parse_smodifier(tmpstr, DEC_RND);
+ if (tval < 0)
+ errx(1, "Bad start argument to the -s flag.");
+ *cstart = tval;
+
+ /* Get start. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr == NULL)
+ errx(1, "Bad argument to the -s flag.");
+ tval = parse_smodifier(tmpstr, DEC_RND_DOWN);
+ if (tval < 0)
+ errx(1, "Bad size argument to the -s flag.");
+ *csize = tval;
+
+#ifdef BOOTSEL
+ /* Get bootmenu. */
+ tmpstr = strtok(NULL, "/");
+ if (tmpstr != NULL)
+ *cbootmenu = strdup(tmpstr);
+ else
+ *cbootmenu = NULL;
+#endif
+
+ return;
+}
+
static int
change_part(int extended, int part, int sysid, daddr_t start, daddr_t size,
char *bootmenu)
{
struct mbr_partition *partp;
@@ -2766,18 +2878,36 @@
if (isdigit((unsigned char)*cp) || *cp == '-') {
acc = strtoll(lbuf, &cp, 10);
len = strcspn(cp, " \t\n");
valid = 0;
if (len != 0 && (flags & DEC_SEC)) {
- if (!strncasecmp(cp, "gb", len)) {
+ if (!strncasecmp(cp, "tb", len)) {
+ acc *= 1024;
+ valid = 1;
+ }
+ if (valid || !strncasecmp(cp, "gb", len)) {
acc *= 1024;
valid = 1;
}
if (valid || !strncasecmp(cp, "mb", len)) {
acc *= SEC_IN_1M;
/* round to whole number of cylinders */
acc += ptn_alignment / 2;
+ acc /= ptn_alignment;
+ valid = 1;
+ }
+ if (!strncmp(cp, "%", len)) {
+ if (acc > 100)
+ return -1;
+ acc = disksectors / 100 * acc;
+ /* round to whole number of cylinders */
+ if (acc <= ptn_alignment / 2)
+ acc += ptn_alignment / 2;
+ else if (flags & DEC_RND_DOWN)
+ acc -= ptn_alignment / 2;
+ else
+ acc += ptn_alignment / 2;
acc /= ptn_alignment;
valid = 1;
}
if (valid || !strncasecmp(cp, "cyl", len)) {
acc *= ptn_alignment;
Home |
Main Index |
Thread Index |
Old Index