Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 25 Jun 2004 12:23:41 +0200 (CEST)
From:      Rene de Vries <rene@tunix.nl>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/68312: be able to create fdisk partions using similar syntax as disklabel/bsdlabel
Message-ID:  <200406251023.i5PANf2W063176@upsilix.tunix.nl>
Resent-Message-ID: <200406251040.i5PAeJmE043099@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         68312
>Category:       bin
>Synopsis:       be able to create fdisk partions using similar syntax as disklabel/bsdlabel
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 25 10:40:19 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Rene de Vries
>Release:        FreeBSD 4.8 i386
>Organization:
Tunix Internet Security & Training
>Environment:
System: FreeBSD upsilix.tunix.nl 4.8 FreeBSD 4.8-RELEASE-p16 #7: Wed Mar 3 15:00:31 CET 2004 rene@upsilix.tunix.nl:/usr/obj/usr/src/sys/UPSILIX i386

>Description:
	Added some cleverness to the 'p' command while parsing a 
	fdisk partition description file.
	Sizes can now also be given in '10M', '20G', etc and wildcards
	can be used to assume sensible defaults.

Example:

/tmp/fdisk.in:
	p 1 165 * 10G
	p 2 165 * 20G
	p 3 165 * *

fdisk -f /tmp/fdisk.in /dev/ad2

>How-To-Repeat:
>Fix:
Index: sbin/i386/fdisk/fdisk.c
===================================================================
RCS file: sbin/i386/fdisk/fdisk.c,v
retrieving revision 1.1.1.4
retrieving revision 1.2
diff -u -r1.1.1.4 -r1.2
--- sbin/i386/fdisk/fdisk.c	2002/08/28 08:57:58	1.1.1.4
+++ sbin/i386/fdisk/fdisk.c	2003/07/22 15:43:21	1.2
@@ -113,6 +113,7 @@
     struct arg {
 	char	argtype;
 	int	arg_val;
+	char	*arg_str;
     }			args[MAX_ARGS];
 } CMD;
 
@@ -1013,6 +1014,10 @@
 	while (1)
 	{
 	    while (isspace(*cp)) ++cp;
+	    if (*cp == '\0')
+	    {
+		break;		/* eol */
+	    }
 	    if (*cp == '#')
 	    {
 		break;		/* found comment */
@@ -1021,16 +1026,21 @@
 	    {
 		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)
+	    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;
 	    command->n_args++;
 	}
@@ -1174,8 +1184,96 @@
 	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
+		{
+			warnx("ERROR line %d: unexpected start: \'%s\'",
+					current_line_number, command->args[2].arg_str);
+			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
+		{
+			char *end;
+			unsigned long val;
+			val = strtol(command->args[3].arg_str, &end, 0);
+			if (command->args[3].arg_str == end) {
+				warnx("ERROR line %d: unexpected size: \'%s\'",
+					current_line_number, command->args[3].arg_str);
+				break;
+			}
+			if (*end != '\0') {
+				if (*end == 'K') 
+				{
+					val *= (1024UL / secsize);
+				}
+				else if (*end == 'M')
+				{
+					val *= (unsigned long)(1024 * 1024 / secsize);
+				}
+				else if (*end == 'G')
+				{
+					val *= (unsigned long)(1024 * 1024 * 1024 / secsize);
+				}
+				else
+				{
+					warnx("ERROR line %d: unexpected modifier: %c (K/M/G)",
+							current_line_number, *end);
+					break;
+				}
+			} 
+			else
+			{
+				warnx("ERROR line %d: unexpected size: %s",
+					current_line_number, command->args[3].arg_str);
+				break;
+			}
+			partp->dp_size = val;
+		}
+		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)
@@ -1189,6 +1287,15 @@
 	    bzero((char *)partp, sizeof (struct dos_partition));
 	    status = 1;
 	    break;
+	}
+
+	if (v_flag)
+	{
+		printf("p%d type=%d start=%lu size=%lu\n",
+				partition,
+				partp->dp_typ,
+				partp->dp_start,
+				partp->dp_size);
 	}
 
 	/*
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200406251023.i5PANf2W063176>