Author: brian
Date: Mon Jun 15 07:17:55 2009
New Revision: 194234
URL: http://svn.freebsd.org/changeset/base/194234

Log:
  MFC: r192745: Enhance the 'p' command so that it understands size
  qualifiers (K/M/G) and so that it understands '*' as 'DTRT'.
  
  PR:           68312

Modified:
  stable/7/sbin/fdisk/   (props changed)
  stable/7/sbin/fdisk/fdisk.8
  stable/7/sbin/fdisk/fdisk.c

Modified: stable/7/sbin/fdisk/fdisk.8
==============================================================================
--- stable/7/sbin/fdisk/fdisk.8 Mon Jun 15 04:31:34 2009        (r194233)
+++ stable/7/sbin/fdisk/fdisk.8 Mon Jun 15 07:17:55 2009        (r194234)
@@ -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: stable/7/sbin/fdisk/fdisk.c
==============================================================================
--- stable/7/sbin/fdisk/fdisk.c Mon Jun 15 04:31:34 2009        (r194233)
+++ stable/7/sbin/fdisk/fdisk.c Mon Jun 15 07:17:55 2009        (r194234)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 
 int iotest;
 
+#define NOSECTORS ((u_int32_t)-1)
 #define LBUF 100
 static char lbuf[LBUF];
 
@@ -107,6 +108,7 @@ typedef struct cmd {
     struct arg {
        char    argtype;
        int     arg_val;
+       char    *arg_str;
     }                  args[MAX_ARGS];
 } CMD;
 
@@ -1001,16 +1003,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++;
        }
@@ -1109,6 +1118,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)
@@ -1134,8 +1170,48 @@ process_partition(CMD *command)
        partp = ((struct dos_partition *) &mboot.parts) + partition - 1;
        bzero((char *)partp, sizeof (struct dos_partition));
        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) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to