[PATCH] Accept parameters to fdisk commands on a single line

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A longstanding nit with fdisk is that you cannot tell it what you want it to 
do all at once, but have to talk to it interactively.  This patch allows you 
to say things like
  d 2
to delete partition 2, and
  c p 3 '' +1G
to create a primary partition, number 3, starting at default position, 1Gb 
big.  A particular annoyance that it fixes is that to delete the first 
partition, you can now use "d 1".

I'm fairly confident that my mail client will mangle this message beyond 
usefulness -- and any guidance / flames as to how I should send the patch 
(and corrections) would be appreciated.

&:-)


>From 5c64073a322f2fb8f63bf77848b45d9e00208074 Mon Sep 17 00:00:00 2001
From: Andrew McGill <andrew@xxxxxxxxxxxx>
Date: Wed, 25 Mar 2009 00:32:56 +0200
Subject: [PATCH] Accept parameters to fdisk commands on a single line


Signed-off-by: Andrew McGill <andrew@xxxxxxxxxxxx>
---
 fdisk/fdisk.c         |  173 
+++++++++++++++++++++++++++++++++++--------------
 fdisk/fdisk.h         |    9 ++-
 fdisk/fdiskbsdlabel.c |    6 +-
 3 files changed, 135 insertions(+), 53 deletions(-)

diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index e3b6857..6b0fdfe 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -806,14 +806,16 @@ dos_set_mbr_id(void) {
 	unsigned long new_id;
 	char *ep;
 	char ps[64];
+        char *mbr_id_string;
 
 	snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "),
 		 dos_read_mbr_id(MBRbuffer));
 
-	if (read_chars(ps) == '\n')
+	mbr_id_string = read_token(RT_ACCEPTBLANK,ps);
+	if (! *mbr_id_string)
 		return;
 
-	new_id = strtoul(line_ptr, &ep, 0);
+	new_id = strtoul(mbr_id_string, &ep, 0);
 	if (*ep != '\n')
 		return;
 
@@ -1103,14 +1105,87 @@ read_line(void)
 	return *line_ptr;
 }
 
-char
-read_char(char *mesg)
+static char *token_ptr = NULL; 
+
+/* Returns a pointer to the next token, if it has already been read, 
otherwise NULL */
+char *
+next_token(void)
+{
+	/* Skip leading whitespace */
+	if (token_ptr) {
+		while (*token_ptr && !isgraph(*token_ptr)) token_ptr++;
+		if (!*token_ptr) token_ptr=NULL;
+	}
+	return token_ptr;
+}
+
+/* Gets a space separated word token from stdin.  If "option newline" is 
given, this
+ * is first token on the line, so any cached line must be discarded.  If an 
empty token
+ * is accepted, a NULL pointer is returned */
+char *
+read_token(int options, char *mesg)
 {
+	int got_eof = 0, showed_mesg = 0;
+	char *token;
+
+	next_token();
 	do {
-		fputs(mesg, stdout);
-		fflush (stdout);	 /* requested by niles@xxxxxxxxx */
-	} while (!read_line());
-	return *line_ptr;
+                if (! token_ptr || options & RT_NEWLINE) {
+                        fputs(mesg,stdout);
+                        showed_mesg++;
+                        fflush(stdout);
+                        reread:
+                        while (fgets(line_buffer, LINE_LENGTH, stdin) == 
NULL ) {
+				if (ferror(stdin)) {
+                                        fprintf(stderr, _("\nError %d: %s on 
input - exiting.\n"),
+						errno, strerror(errno));
+                                        exit(1);
+				}
+                                if (++got_eof >= 3) {
+                                        fprintf(stderr, _("\ngot EOF thrice - 
exiting..\n"));
+                                        exit(1);
+                                }
+                        }
+                        token_ptr=line_buffer;
+                }
+		/* Sometimes we accept a blank line as input, if it is really blank */
+		if (options & RT_ACCEPTBLANK && *token_ptr == '\n') {
+                        token_ptr = NULL;
+                        *line_buffer = 0;
+			return line_buffer;
+		}
+        } while (!next_token()); /* skip whitespace */
+
+	/* Null terminate at the first space, or matching quote */
+        if (*token_ptr=='"' || *token_ptr=='\'') {
+                token=token_ptr+1;
+                token_ptr = strchr(token_ptr+1,*token_ptr);
+                if (token_ptr) *token_ptr++=0;
+        }
+        else {
+            token=token_ptr;
+            while (isgraph(*token_ptr)) {
+                    token_ptr++;
+            }
+            if (*token_ptr) {
+                    *token_ptr++ = 0;
+            }
+            else {
+                    token_ptr = NULL;
+            }
+        }
+        if (!showed_mesg && *mesg) { /* this was entered without a prompt, so 
show prompt and value now */
+                fprintf(stdout,"%s%s\n",mesg,token);
+                fflush(stdout);
+        }
+	return token;
+}
+
+
+char
+read_char(int options, char *mesg)
+{
+        return * (read_token(options, mesg)) ;
 }
 
 char
@@ -1129,18 +1204,19 @@ int
 read_hex(struct systypes *sys)
 {
         int hex;
+        char *hexstring;
 
         while (1)
         {
-           read_char(_("Hex code (type L to list codes): "));
-           if (tolower(*line_ptr) == 'l')
+           hexstring = read_token(RT_NORMAL,_("Hex code (type L to list 
codes): "));
+           if (tolower(*hexstring) == 'l')
                list_types(sys);
-	   else if (isxdigit (*line_ptr))
+	   else if (isxdigit (*hexstring))
 	   {
 	      hex = 0;
 	      do
-		 hex = hex << 4 | hex_val(*line_ptr++);
-	      while (isxdigit(*line_ptr));
+		 hex = hex << 4 | hex_val(*hexstring++);
+	      while (isxdigit(*hexstring));
 	      return hex;
 	   }
         }
@@ -1158,7 +1234,7 @@ read_int(unsigned int low, unsigned int dflt, unsigned 
int high,
 	 unsigned int base, char *mesg)
 {
 	unsigned int i;
-	int default_ok = 1;
+	int default_ok = RT_ACCEPTBLANK;
 	static char *ms = NULL;
 	static int mslen = 0;
 
@@ -1180,66 +1256,65 @@ read_int(unsigned int low, unsigned int dflt, unsigned 
int high,
 
 	while (1) {
 		int use_default = default_ok;
+		char *numeric, *suffix;
 
 		/* ask question and read answer */
-		while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
-		       && *line_ptr != '-' && *line_ptr != '+')
-			continue;
+		do {
+			numeric=read_token(RT_NORMAL | default_ok,ms);
+		} while (*numeric && !isdigit(*numeric) && *numeric != '-' && 
*numeric != '+');
 
-		if (*line_ptr == '+' || *line_ptr == '-') {
-			int minus = (*line_ptr == '-');
+		if (*numeric == '+' || *numeric == '-') {
+			int minus = (*numeric == '-');
 			int absolute = 0;
-			int suflen;
 
-			i = atoi(line_ptr+1);
+			i = atoi(numeric+1);
 
-			while (isdigit(*++line_ptr))
+			while (isdigit(*++numeric))
 				use_default = 0;
+			suffix=numeric;
+                        if (*suffix==0 && next_token()) {
+				suffix=read_token(RT_NORMAL,"");
+                        }
 
-			suflen = strlen(line_ptr) - 1;
-
-			while(isspace(*(line_ptr + suflen)))
-				*(line_ptr + suflen--) = '\0';
-
-			if ((*line_ptr == 'C' || *line_ptr == 'c') &&
-			    *(line_ptr + 1) == '\0') {
+			if ((*suffix == 'C' || *suffix == 'c') &&
+			    *(suffix + 1) == '\0') {
 				/*
 				 * Cylinders
 				 */
 				if (!display_in_cyl_units)
 					i *= heads * sectors;
-			} else if (*line_ptr &&
-				   *(line_ptr + 1) == 'B' &&
-				   *(line_ptr + 2) == '\0') {
+			} else if (*suffix &&
+				   *(suffix + 1) == 'B' &&
+				   *(suffix + 2) == '\0') {
 				/*
 				 * 10^N
 				 */
-				if (*line_ptr == 'K')
+				if (*suffix == 'K')
 					absolute = 1000;
-				else if (*line_ptr == 'M')
+				else if (*suffix == 'M')
 					absolute = 1000000;
-				else if (*line_ptr == 'G')
+				else if (*suffix == 'G')
 					absolute = 1000000000;
 				else
 					absolute = -1;
-			} else if (*line_ptr &&
-				   *(line_ptr + 1) == '\0') {
+			} else if (*suffix &&
+				   *(suffix + 1) == '\0') {
 				/*
 				 * 2^N
 				 */
-				if (*line_ptr == 'K')
+				if (*suffix == 'K')
 					absolute = 1 << 10;
-				else if (*line_ptr == 'M')
+				else if (*suffix == 'M')
 					absolute = 1 << 20;
-				else if (*line_ptr == 'G')
+				else if (*suffix == 'G')
 					absolute = 1 << 30;
 				else
 					absolute = -1;
-			} else if (*line_ptr != '\0')
+			} else if (*suffix != '\0')
 				absolute = -1;
 
 			if (absolute == -1)  {
-				printf(_("Unsupported suffix: '%s'.\n"), line_ptr);
+				printf(_("Unsupported suffix: '%s'.\n"), suffix);
 				printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n"
 					 "            2^N: K  (KibiByte), M  (MebiByte), G  (GibiByte)\n"));
 				continue;
@@ -1259,9 +1334,9 @@ read_int(unsigned int low, unsigned int dflt, unsigned 
int high,
 				i = -i;
 			i += base;
 		} else {
-			i = atoi(line_ptr);
-			while (isdigit(*line_ptr)) {
-				line_ptr++;
+			i = atoi(numeric);
+			while (isdigit(*numeric)) {
+				numeric++;
 				use_default = 0;
 			}
 		}
@@ -2217,7 +2292,7 @@ new_partition(void) {
 			   "partition (1-4)\n"), extended_offset ?
 			 _("l   logical (5 or over)") : _("e   extended"));
 		while (1) {
-			if ((c = tolower(read_char(line))) == 'p') {
+			if ((c = tolower(read_char(RT_NORMAL,line))) == 'p') {
 				int i = get_nonexisting_partition(0, 4);
 				if (i >= 0)
 					add_partition(i, LINUX_NATIVE);
@@ -2379,7 +2454,7 @@ xselect(void) {
 
 	while(1) {
 		putchar('\n');
-		c = tolower(read_char(_("Expert command (m for help): ")));
+		c = tolower(read_char(RT_NORMAL,_("Expert command (m for help): ")));
 		switch (c) {
 		case 'a':
 			if (sun_label)
@@ -2584,7 +2659,6 @@ unknown_command(int c) {
 }
 
 
-
 int
 main(int argc, char **argv) {
 	int j, c;
@@ -2724,7 +2798,7 @@ main(int argc, char **argv) {
 
 	while (1) {
 		putchar('\n');
-		c = tolower(read_char(_("Command (m for help): ")));
+		c = tolower(read_char(RT_NEWLINE,_("Command (m for help): ")));
 		switch (c) {
 		case 'a':
 			if (dos_label)
@@ -2829,3 +2903,4 @@ main(int argc, char **argv) {
 	}
 	return 0;
 }
+
diff --git a/fdisk/fdisk.h b/fdisk/fdisk.h
index 75dd88e..b970ecb 100644
--- a/fdisk/fdisk.h
+++ b/fdisk/fdisk.h
@@ -68,7 +68,8 @@ extern int get_boot(enum action what);
 extern int  get_partition(int warn, int max);
 extern void list_types(struct systypes *sys);
 extern int read_line (void);
-extern char read_char(char *mesg);
+extern char *read_token(int options, char *mesg);
+extern char read_char(int options, char *mesg);
 extern int read_hex(struct systypes *sys);
 extern void reread_partition_table(int leave);
 extern struct partition *get_part_table(int);
@@ -108,3 +109,9 @@ extern void xbsd_print_disklabel(int);
 extern int valid_part_table_flag(unsigned char *b);
 
 #define PROC_PARTITIONS "/proc/partitions"
+
+/* Constants for read_token */
+#define RT_NORMAL	0	/* Regular space delimited input */
+#define RT_NEWLINE	0x1	/* Discard existing input */
+#define RT_ACCEPTBLANK	0x2	/* Accept empty input */
+
diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c
index 377b64e..3fd97b7 100644
--- a/fdisk/fdiskbsdlabel.c
+++ b/fdisk/fdiskbsdlabel.c
@@ -201,7 +201,7 @@ bselect (void) {
 
   while (1) {
     putchar ('\n');
-    switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) 
{
+    switch (tolower (read_char (RT_NEWLINE, _("BSD disklabel command (m for 
help): ")))) {
       case 'd':
 	xbsd_delete_part ();
 	break;
@@ -424,7 +424,7 @@ xbsd_create_disklabel (void) {
 #endif
 
 	while (1) {
-		c = read_char (_("Do you want to create a disklabel? (y/n) "));
+		c = read_char (RT_NEWLINE, _("Do you want to create a disklabel? (y/n) "));
 		if (tolower(c) == 'y') {
 			if (xbsd_initlabel (
 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
@@ -598,7 +598,7 @@ xbsd_get_part_index (int max)
 
   snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
   do
-     l = tolower (read_char (prompt));
+     l = tolower (read_char (RT_NORMAL, prompt));
   while (l < 'a' || l > 'a' + max - 1);
   return l - 'a';
 }
-- 
1.5.4.3
--
To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux