summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-04-10 13:17:50 +0100
committerRichard Jones <rjones@redhat.com>2010-04-12 19:04:13 +0100
commit7095bab6110a6e10d52c6c873082df8185aefd8c (patch)
tree1dfc3cc8e0cd17eecf436ac3c71914ad860e2459
parentb15faa431906acfee94245c2d951ea285eaf0d0b (diff)
downloadlibguestfs-7095bab6110a6e10d52c6c873082df8185aefd8c.tar.gz
libguestfs-7095bab6110a6e10d52c6c873082df8185aefd8c.tar.xz
libguestfs-7095bab6110a6e10d52c6c873082df8185aefd8c.zip
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. (cherry picked from commit cb9350019cc6382a35c98f522c9c4d221c92b605)
-rw-r--r--daemon/parted.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/daemon/parted.c b/daemon/parted.c
index ff6cca11..b1750a51 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;
}