summaryrefslogtreecommitdiffstats
path: root/sbin/fdisk
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2009-05-25 09:23:26 +0000
committerbrian <brian@FreeBSD.org>2009-05-25 09:23:26 +0000
commitc60c7e0b06b9ba8e327e7c42a0125442344971d6 (patch)
treea7d3c7fbf531e98d77da60d227b941be99385634 /sbin/fdisk
parent5dbd8394e8a84dd9afa24d365b04d3d52f20640a (diff)
downloadFreeBSD-src-c60c7e0b06b9ba8e327e7c42a0125442344971d6.zip
FreeBSD-src-c60c7e0b06b9ba8e327e7c42a0125442344971d6.tar.gz
Enhance the 'p' command so that it understands size qualifiers (K/M/G) and
so that it understands '*' as 'DTRT'. PR: 68312 Submitted by: Rene de Vries - rene at tunix dot nl (mostly) MFC after: 3 weeks
Diffstat (limited to 'sbin/fdisk')
-rw-r--r--sbin/fdisk/fdisk.836
-rw-r--r--sbin/fdisk/fdisk.c88
2 files changed, 118 insertions, 6 deletions
diff --git a/sbin/fdisk/fdisk.8 b/sbin/fdisk/fdisk.8
index 1537266..0ffdeff 100644
--- a/sbin/fdisk/fdisk.8
+++ b/sbin/fdisk/fdisk.8
@@ -372,6 +372,31 @@ starting at sector
for
.Ar length
sectors.
+If the
+.Ar start
+or
+.Ar length
+is suffixed with a
+.Em K ,
+.Em M
+or
+.Em G ,
+it is taken as a
+.Em Kilobyte ,
+.Em Megabyte
+or
+.Em Gigabyte
+measurement respectively.
+If the
+.Ar start
+is given as
+.Qq *
+it is set to the value of the previous partition end.
+If the
+.Ar length
+is given as
+.Qq *
+the partition end is set to the end of the disk.
.Pp
Only those slices explicitly mentioned by these lines are modified;
any slice not referenced by a
@@ -421,6 +446,17 @@ for 2503871 sectors (note: these numbers will be rounded upwards and
downwards to correspond to head and cylinder boundaries):
.Pp
.Dl "p 1 165 1 2503871"
+.Pp
+Example: to set slices 1, 2 and 4 to
+.Fx
+slices, the first being 2 Gigabytes, the second being 10 Gigabytes and the
+forth being the remainder of the disk (again, numbers will be rounded
+appropriately):
+.Pp
+.Dl "p 1 165 63 2G"
+.Dl "p 2 165 * 10G"
+.Dl "p 3 0 0 0"
+.Dl "p 4 165 * *"
.It Ic a Ar slice
Make
.Ar slice
diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c
index c500d03..1e121bb 100644
--- a/sbin/fdisk/fdisk.c
+++ b/sbin/fdisk/fdisk.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
int iotest;
+#define NOSECTORS ((u_int32_t)-1)
#define LBUF 100
static char lbuf[LBUF];
@@ -106,6 +107,7 @@ typedef struct cmd {
struct arg {
char argtype;
int arg_val;
+ char *arg_str;
} args[MAX_ARGS];
} CMD;
@@ -970,16 +972,23 @@ parse_config_line(char *line, CMD *command)
*/
while (1) {
while (isspace(*cp)) ++cp;
+ if (*cp == '\0')
+ break; /* eol */
if (*cp == '#')
break; /* found comment */
if (isalpha(*cp))
command->args[command->n_args].argtype = *cp++;
- if (!isdigit(*cp))
- break; /* assume end of line */
end = NULL;
command->args[command->n_args].arg_val = strtol(cp, &end, 0);
- if (cp == end)
- break; /* couldn't parse number */
+ if (cp == end || (!isspace(*end) && *end != '\0')) {
+ char ch;
+ end = cp;
+ while (!isspace(*end) && *end != '\0') ++end;
+ ch = *end; *end = '\0';
+ command->args[command->n_args].arg_str = strdup(cp);
+ *end = ch;
+ } else
+ command->args[command->n_args].arg_str = NULL;
cp = end;
command->n_args++;
}
@@ -1078,6 +1087,33 @@ process_geometry(CMD *command)
return (status);
}
+static u_int32_t
+str2sectors(const char *str)
+{
+ char *end;
+ unsigned long val;
+
+ val = strtoul(str, &end, 0);
+ if (str == end || *end == '\0') {
+ warnx("ERROR line %d: unexpected size: \'%s\'",
+ current_line_number, str);
+ return NOSECTORS;
+ }
+
+ if (*end == 'K')
+ val *= 1024UL / secsize;
+ else if (*end == 'M')
+ val *= 1024UL * 1024UL / secsize;
+ else if (*end == 'G')
+ val *= 1024UL * 1024UL * 1024UL / secsize;
+ else {
+ warnx("ERROR line %d: unexpected modifier: %c "
+ "(not K/M/G)", current_line_number, *end);
+ return NOSECTORS;
+ }
+
+ return val;
+}
static int
process_partition(CMD *command)
@@ -1103,8 +1139,48 @@ process_partition(CMD *command)
partp = &mboot.parts[partition - 1];
bzero(partp, sizeof (*partp));
partp->dp_typ = command->args[1].arg_val;
- partp->dp_start = command->args[2].arg_val;
- partp->dp_size = command->args[3].arg_val;
+ if (command->args[2].arg_str != NULL) {
+ if (strcmp(command->args[2].arg_str, "*") == 0) {
+ int i;
+ partp->dp_start = dos_sectors;
+ for (i = 1; i < partition; i++) {
+ struct dos_partition *prev_partp;
+ prev_partp = ((struct dos_partition *)
+ &mboot.parts) + i - 1;
+ if (prev_partp->dp_typ != 0)
+ partp->dp_start = prev_partp->dp_start +
+ prev_partp->dp_size;
+ }
+ if (partp->dp_start % dos_sectors != 0) {
+ prev_head_boundary = partp->dp_start /
+ dos_sectors * dos_sectors;
+ partp->dp_start = prev_head_boundary +
+ dos_sectors;
+ }
+ } else {
+ partp->dp_start = str2sectors(command->args[2].arg_str);
+ if (partp->dp_start == NOSECTORS)
+ break;
+ }
+ } else
+ partp->dp_start = command->args[2].arg_val;
+
+ if (command->args[3].arg_str != NULL) {
+ if (strcmp(command->args[3].arg_str, "*") == 0)
+ partp->dp_size = ((disksecs / dos_cylsecs) *
+ dos_cylsecs) - partp->dp_start;
+ else {
+ partp->dp_size = str2sectors(command->args[3].arg_str);
+ if (partp->dp_size == NOSECTORS)
+ break;
+ }
+ prev_cyl_boundary = ((partp->dp_start + partp->dp_size) /
+ dos_cylsecs) * dos_cylsecs;
+ if (prev_cyl_boundary > partp->dp_start)
+ partp->dp_size = prev_cyl_boundary - partp->dp_start;
+ } else
+ partp->dp_size = command->args[3].arg_val;
+
max_end = partp->dp_start + partp->dp_size;
if (partp->dp_typ == 0) {
OpenPOWER on IntegriCloud