svn commit: r192745 - head/sbin/fdisk

Brian Somers brian at FreeBSD.org
Mon May 25 09:23:27 UTC 2009


Author: brian
Date: Mon May 25 09:23:26 2009
New Revision: 192745
URL: http://svn.freebsd.org/changeset/base/192745

Log:
  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

Modified:
  head/sbin/fdisk/fdisk.8
  head/sbin/fdisk/fdisk.c

Modified: head/sbin/fdisk/fdisk.8
==============================================================================
--- head/sbin/fdisk/fdisk.8	Mon May 25 09:09:43 2009	(r192744)
+++ head/sbin/fdisk/fdisk.8	Mon May 25 09:23:26 2009	(r192745)
@@ -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
 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

Modified: head/sbin/fdisk/fdisk.c
==============================================================================
--- head/sbin/fdisk/fdisk.c	Mon May 25 09:09:43 2009	(r192744)
+++ head/sbin/fdisk/fdisk.c	Mon May 25 09:23:26 2009	(r192745)
@@ -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 *comma
 	 */
 	    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) {


More information about the svn-src-all mailing list