From cb9350019cc6382a35c98f522c9c4d221c92b605 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Sat, 10 Apr 2010 13:17:50 +0100 Subject: [PATCH] daemon: More reliable parsing of the output from 'parted print'. Previously we used strtok. However this has the problem that strtok considers multiple delimiter characters to be like a single delimiter, eg. "1:::2" would be parsed the same as "1:2". In other words, the previous code would skip over or fail if there are empty fields. --- daemon/parted.c | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/daemon/parted.c b/daemon/parted.c index ff6cca1..b1750a5 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -224,6 +224,36 @@ do_part_set_name (const char *device, int partnum, const char *name) return 0; } +/* Return the nth field from a string of ':'/';'-delimited strings. + * Useful for parsing the return value from print_partition_table + * function below. + */ +static char * +get_table_field (const char *line, int n) +{ + const char *p = line; + + while (*p && n > 0) { + p += strcspn (p, ":;") + 1; + n--; + } + + if (n > 0) { + reply_with_error ("not enough fields in output of parted print command: %s", + line); + return NULL; + } + + size_t len = strcspn (p, ":;"); + char *q = strndup (p, len); + if (q == NULL) { + reply_with_perror ("strndup"); + return NULL; + } + + return q; +} + static char ** print_partition_table (const char *device) { @@ -269,31 +299,15 @@ print_partition_table (const char *device) char * do_part_get_parttype (const char *device) { - char **lines; - char *r; - - lines = print_partition_table (device); + char **lines = print_partition_table (device); if (!lines) return NULL; /* lines[1] is something like: * "/dev/sda:1953525168s:scsi:512:512:msdos:ATA Hitachi HDT72101;" */ - if (strtok (lines[1], ":") == NULL /* device */ - || strtok (NULL, ":") == NULL /* size */ - || strtok (NULL, ":") == NULL /* transport */ - || strtok (NULL, ":") == NULL /* sector size */ - || strtok (NULL, ":") == NULL /* physical sector size */ - || (r = strtok (NULL, ":")) == NULL /* return value */ - ) { - reply_with_error ("too few fields in output from parted print command: %s", lines[1]); - free_strings (lines); - return NULL; - } - - r = strdup (r); - if (!r) { - reply_with_perror ("strdup"); + char *r = get_table_field (lines[1], 5); + if (r == NULL) { free_strings (lines); return NULL; } -- 1.8.3.1