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
This commit is contained in:
Brian Somers 2009-05-25 09:23:26 +00:00
parent 3f33fa335e
commit d1c77156d8
2 changed files with 118 additions and 6 deletions

View File

@ -372,6 +372,31 @@ starting at sector
for for
.Ar length .Ar length
sectors. 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 .Pp
Only those slices explicitly mentioned by these lines are modified; Only those slices explicitly mentioned by these lines are modified;
any slice not referenced by a 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): downwards to correspond to head and cylinder boundaries):
.Pp .Pp
.Dl "p 1 165 1 2503871" .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 .It Ic a Ar slice
Make Make
.Ar slice .Ar slice

View File

@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
int iotest; int iotest;
#define NOSECTORS ((u_int32_t)-1)
#define LBUF 100 #define LBUF 100
static char lbuf[LBUF]; static char lbuf[LBUF];
@ -106,6 +107,7 @@ typedef struct cmd {
struct arg { struct arg {
char argtype; char argtype;
int arg_val; int arg_val;
char *arg_str;
} args[MAX_ARGS]; } args[MAX_ARGS];
} CMD; } CMD;
@ -970,16 +972,23 @@ parse_config_line(char *line, CMD *command)
*/ */
while (1) { while (1) {
while (isspace(*cp)) ++cp; while (isspace(*cp)) ++cp;
if (*cp == '\0')
break; /* eol */
if (*cp == '#') if (*cp == '#')
break; /* found comment */ break; /* found comment */
if (isalpha(*cp)) if (isalpha(*cp))
command->args[command->n_args].argtype = *cp++; command->args[command->n_args].argtype = *cp++;
if (!isdigit(*cp))
break; /* assume end of line */
end = NULL; end = NULL;
command->args[command->n_args].arg_val = strtol(cp, &end, 0); command->args[command->n_args].arg_val = strtol(cp, &end, 0);
if (cp == end) if (cp == end || (!isspace(*end) && *end != '\0')) {
break; /* couldn't parse number */ 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; cp = end;
command->n_args++; command->n_args++;
} }
@ -1078,6 +1087,33 @@ process_geometry(CMD *command)
return (status); 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 static int
process_partition(CMD *command) process_partition(CMD *command)
@ -1103,8 +1139,48 @@ process_partition(CMD *command)
partp = &mboot.parts[partition - 1]; partp = &mboot.parts[partition - 1];
bzero(partp, sizeof (*partp)); bzero(partp, sizeof (*partp));
partp->dp_typ = command->args[1].arg_val; partp->dp_typ = command->args[1].arg_val;
partp->dp_start = command->args[2].arg_val; if (command->args[2].arg_str != NULL) {
partp->dp_size = command->args[3].arg_val; 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; max_end = partp->dp_start + partp->dp_size;
if (partp->dp_typ == 0) { if (partp->dp_typ == 0) {