Chen Hanxiao
2015-Mar-13 09:04 UTC
[Libguestfs] [PATCH] part-list: add support for show partition type
We lack of showing parttition type for part-list command. This patch will add support for this. Also 'parted -m' did not provide partition type info, remove code section for 'parted -m' process. Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com> --- daemon/parted.c | 155 ++++++++++++++++++++++++++------------------------- generator/structs.ml | 1 + resize/resize.ml | 2 +- 3 files changed, 82 insertions(+), 76 deletions(-) diff --git a/daemon/parted.c b/daemon/parted.c index a7bcb99..312b15f 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -33,6 +33,10 @@ GUESTFSD_EXT_CMD(str_parted, parted); GUESTFSD_EXT_CMD(str_sfdisk, sfdisk); GUESTFSD_EXT_CMD(str_sgdisk, sgdisk); +#ifndef PARTED_NO_M +# define PARTED_NO_M 0 +#endif + /* Notes: * * Parted 1.9 sends error messages to stdout, hence use of the @@ -451,11 +455,7 @@ do_part_get_parttype (const char *device) guestfs_int_partition_list * do_part_list (const char *device) { - int parted_has_m_opt = test_parted_m_opt (); - if (parted_has_m_opt == -1) - return NULL; - - CLEANUP_FREE char *out = print_partition_table (device, parted_has_m_opt); + CLEANUP_FREE char *out = print_partition_table (device, PARTED_NO_M); if (!out) return NULL; @@ -466,88 +466,86 @@ do_part_list (const char *device) guestfs_int_partition_list *r; - if (parted_has_m_opt) { - /* New-style parsing using the "machine-readable" format from - * 'parted -m'. - * - * lines[0] is "BYT;", lines[1] is the device line which we ignore, - * lines[2..] are the partitions themselves. Count how many. - */ - size_t nr_rows = 0, row; - for (row = 2; lines[row] != NULL; ++row) - ++nr_rows; - - r = malloc (sizeof *r); - if (r == NULL) { - reply_with_perror ("malloc"); - return NULL; + /* Old-style. Start at the line following "^Number", up to the + * next blank line. + */ + size_t start = 0, end = 0, has_type = 0, row; + + for (row = 0; lines[row] != NULL; ++row) + if (STRPREFIX (lines[row], "Number")) { + start = row+1; + /* check whether output of parted has 'Type' field */ + if (strstr (lines[row], "Type")) + has_type = 1; + break; } - r->guestfs_int_partition_list_len = nr_rows; - r->guestfs_int_partition_list_val - malloc (nr_rows * sizeof (guestfs_int_partition)); - if (r->guestfs_int_partition_list_val == NULL) { - reply_with_perror ("malloc"); - goto error2; + + if (start == 0) { + reply_with_error ("parted output has no \"Number\" line"); + return NULL; + } + + for (row = start; lines[row] != NULL; ++row) + if (STREQ (lines[row], "")) { + end = row; + break; } - /* Now parse the lines. */ - size_t i; - for (i = 0, row = 2; lines[row] != NULL; ++i, ++row) { - if (sscanf (lines[row], "%d:%" SCNi64 "B:%" SCNi64 "B:%" SCNi64 "B", + if (end == 0) { + reply_with_error ("parted output has no blank after end of table"); + return NULL; + } + + size_t nr_rows = end - start; + + r = malloc (sizeof *r); + if (r == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + r->guestfs_int_partition_list_len = nr_rows; + r->guestfs_int_partition_list_val + malloc (nr_rows * sizeof (guestfs_int_partition)); + if (r->guestfs_int_partition_list_val == NULL) { + reply_with_perror ("malloc"); + goto error2; + } + + /* Now parse the lines. */ + size_t i, k; + if (has_type) { + /* hold type such as primary, logical and extended */ + char type_temp[16]; + for (i = 0, row = start; row < end; ++i, ++row) { + if (sscanf (lines[row], " %d %" SCNi64 "B %" SCNi64 "B %" SCNi64 "B" "%s", &r->guestfs_int_partition_list_val[i].part_num, &r->guestfs_int_partition_list_val[i].part_start, &r->guestfs_int_partition_list_val[i].part_end, - &r->guestfs_int_partition_list_val[i].part_size) != 4) { + &r->guestfs_int_partition_list_val[i].part_size, + type_temp) != 5) { reply_with_error ("could not parse row from output of parted print command: %s", lines[row]); goto error3; } - } - } - else { - /* Old-style. Start at the line following "^Number", up to the - * next blank line. - */ - size_t start = 0, end = 0, row; - for (row = 0; lines[row] != NULL; ++row) - if (STRPREFIX (lines[row], "Number")) { - start = row+1; - break; + if (STRPREFIX (type_temp, "primary")) { + r->guestfs_int_partition_list_val[i].part_type = strdup("primary"); + if (r->guestfs_int_partition_list_val[i].part_type == NULL) + goto error4; + } else if (STRPREFIX (type_temp, "logical")) { + r->guestfs_int_partition_list_val[i].part_type = strdup("logical"); + if (r->guestfs_int_partition_list_val[i].part_type == NULL) + goto error4; + } else if (STRPREFIX (type_temp, "extended")) { + r->guestfs_int_partition_list_val[i].part_type = strdup("extended"); + if (r->guestfs_int_partition_list_val[i].part_type == NULL) + goto error4; + } else { + r->guestfs_int_partition_list_val[i].part_type = strdup(""); + if (r->guestfs_int_partition_list_val[i].part_type == NULL) + goto error4; } - - if (start == 0) { - reply_with_error ("parted output has no \"Number\" line"); - return NULL; } - - for (row = start; lines[row] != NULL; ++row) - if (STREQ (lines[row], "")) { - end = row; - break; - } - - if (end == 0) { - reply_with_error ("parted output has no blank after end of table"); - return NULL; - } - - size_t nr_rows = end - start; - - r = malloc (sizeof *r); - if (r == NULL) { - reply_with_perror ("malloc"); - return NULL; - } - r->guestfs_int_partition_list_len = nr_rows; - r->guestfs_int_partition_list_val - malloc (nr_rows * sizeof (guestfs_int_partition)); - if (r->guestfs_int_partition_list_val == NULL) { - reply_with_perror ("malloc"); - goto error2; - } - - /* Now parse the lines. */ - size_t i; + } else { for (i = 0, row = start; row < end; ++i, ++row) { if (sscanf (lines[row], " %d %" SCNi64 "B %" SCNi64 "B %" SCNi64 "B", &r->guestfs_int_partition_list_val[i].part_num, @@ -557,11 +555,18 @@ do_part_list (const char *device) reply_with_error ("could not parse row from output of parted print command: %s", lines[row]); goto error3; } + + r->guestfs_int_partition_list_val[i].part_type = strdup(""); + if (r->guestfs_int_partition_list_val[i].part_type == NULL) + goto error4; } } return r; + error4: + for (k = 0; k <= i; k++) + free (r->guestfs_int_partition_list_val[k].part_type); error3: free (r->guestfs_int_partition_list_val); error2: diff --git a/generator/structs.ml b/generator/structs.ml index ea110a1..e7a9fa6 100644 --- a/generator/structs.ml +++ b/generator/structs.ml @@ -240,6 +240,7 @@ let structs = [ "part_start", FBytes; "part_end", FBytes; "part_size", FBytes; + "part_type", FString; ]; s_camel_name = "Partition" }; diff --git a/resize/resize.ml b/resize/resize.ml index 84fd6d4..8f8f67f 100644 --- a/resize/resize.ml +++ b/resize/resize.ml @@ -1078,7 +1078,7 @@ read the man page virt-resize(1). *) p_name = ""; p_part = { G.part_num = 0l; part_start = 0L; part_end = 0L; - part_size = 0L }; + part_size = 0L; part_type = "" }; p_bootable = false; p_id = No_ID; p_type = ContentUnknown; p_label = None; p_guid = None; -- 2.1.0
Pino Toscano
2015-Mar-13 10:32 UTC
Re: [Libguestfs] [PATCH] part-list: add support for show partition type
On Friday 13 March 2015 05:04:56 Chen Hanxiao wrote:> We lack of showing parttition type for part-list command. > This patch will add support for this.You cannot extend the struct returned by part_init with new members, that will cause compatibility issues with existing C users of that API.> Also 'parted -m' did not provide partition type info, > remove code section for 'parted -m' process. > > Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com> > --- > daemon/parted.c | 155 ++++++++++++++++++++++++++------------------------- > generator/structs.ml | 1 + > resize/resize.ml | 2 +- > 3 files changed, 82 insertions(+), 76 deletions(-) > > diff --git a/daemon/parted.c b/daemon/parted.c > index a7bcb99..312b15f 100644 > --- a/daemon/parted.c > +++ b/daemon/parted.c > @@ -33,6 +33,10 @@ GUESTFSD_EXT_CMD(str_parted, parted); > GUESTFSD_EXT_CMD(str_sfdisk, sfdisk); > GUESTFSD_EXT_CMD(str_sgdisk, sgdisk); > > +#ifndef PARTED_NO_M > +# define PARTED_NO_M 0 > +#endif > + > /* Notes: > * > * Parted 1.9 sends error messages to stdout, hence use of the > @@ -451,11 +455,7 @@ do_part_get_parttype (const char *device) > guestfs_int_partition_list * > do_part_list (const char *device) > { > - int parted_has_m_opt = test_parted_m_opt (); > - if (parted_has_m_opt == -1) > - return NULL; > - > - CLEANUP_FREE char *out = print_partition_table (device, parted_has_m_opt); > + CLEANUP_FREE char *out = print_partition_table (device, PARTED_NO_M); > if (!out) > return NULL; > > @@ -466,88 +466,86 @@ do_part_list (const char *device) > > guestfs_int_partition_list *r; > > - if (parted_has_m_opt) { > - /* New-style parsing using the "machine-readable" format from > - * 'parted -m'. > - * > - * lines[0] is "BYT;", lines[1] is the device line which we ignore, > - * lines[2..] are the partitions themselves. Count how many. > - */ > - size_t nr_rows = 0, row; > - for (row = 2; lines[row] != NULL; ++row) > - ++nr_rows; > - > - r = malloc (sizeof *r); > - if (r == NULL) { > - reply_with_perror ("malloc"); > - return NULL; > + /* Old-style. Start at the line following "^Number", up to the > + * next blank line. > + */ > + size_t start = 0, end = 0, has_type = 0, row; > + > + for (row = 0; lines[row] != NULL; ++row) > + if (STRPREFIX (lines[row], "Number")) { > + start = row+1; > + /* check whether output of parted has 'Type' field */ > + if (strstr (lines[row], "Type")) > + has_type = 1; > + break; > } > - r->guestfs_int_partition_list_len = nr_rows; > - r->guestfs_int_partition_list_val > - malloc (nr_rows * sizeof (guestfs_int_partition)); > - if (r->guestfs_int_partition_list_val == NULL) { > - reply_with_perror ("malloc"); > - goto error2; > + > + if (start == 0) { > + reply_with_error ("parted output has no \"Number\" line"); > + return NULL; > + } > + > + for (row = start; lines[row] != NULL; ++row) > + if (STREQ (lines[row], "")) { > + end = row; > + break; > } > > - /* Now parse the lines. */ > - size_t i; > - for (i = 0, row = 2; lines[row] != NULL; ++i, ++row) { > - if (sscanf (lines[row], "%d:%" SCNi64 "B:%" SCNi64 "B:%" SCNi64 "B", > + if (end == 0) { > + reply_with_error ("parted output has no blank after end of table"); > + return NULL; > + } > + > + size_t nr_rows = end - start; > + > + r = malloc (sizeof *r); > + if (r == NULL) { > + reply_with_perror ("malloc"); > + return NULL; > + } > + r->guestfs_int_partition_list_len = nr_rows; > + r->guestfs_int_partition_list_val > + malloc (nr_rows * sizeof (guestfs_int_partition)); > + if (r->guestfs_int_partition_list_val == NULL) { > + reply_with_perror ("malloc"); > + goto error2; > + } > + > + /* Now parse the lines. */ > + size_t i, k; > + if (has_type) { > + /* hold type such as primary, logical and extended */ > + char type_temp[16]; > + for (i = 0, row = start; row < end; ++i, ++row) { > + if (sscanf (lines[row], " %d %" SCNi64 "B %" SCNi64 "B %" SCNi64 "B" "%s", > &r->guestfs_int_partition_list_val[i].part_num, > &r->guestfs_int_partition_list_val[i].part_start, > &r->guestfs_int_partition_list_val[i].part_end, > - &r->guestfs_int_partition_list_val[i].part_size) != 4) { > + &r->guestfs_int_partition_list_val[i].part_size, > + type_temp) != 5) { > reply_with_error ("could not parse row from output of parted print command: %s", lines[row]); > goto error3; > } > - } > - } > - else { > - /* Old-style. Start at the line following "^Number", up to the > - * next blank line. > - */ > - size_t start = 0, end = 0, row; > > - for (row = 0; lines[row] != NULL; ++row) > - if (STRPREFIX (lines[row], "Number")) { > - start = row+1; > - break; > + if (STRPREFIX (type_temp, "primary")) { > + r->guestfs_int_partition_list_val[i].part_type = strdup("primary"); > + if (r->guestfs_int_partition_list_val[i].part_type == NULL) > + goto error4; > + } else if (STRPREFIX (type_temp, "logical")) { > + r->guestfs_int_partition_list_val[i].part_type = strdup("logical"); > + if (r->guestfs_int_partition_list_val[i].part_type == NULL) > + goto error4; > + } else if (STRPREFIX (type_temp, "extended")) { > + r->guestfs_int_partition_list_val[i].part_type = strdup("extended"); > + if (r->guestfs_int_partition_list_val[i].part_type == NULL) > + goto error4; > + } else { > + r->guestfs_int_partition_list_val[i].part_type = strdup(""); > + if (r->guestfs_int_partition_list_val[i].part_type == NULL) > + goto error4; > } > - > - if (start == 0) { > - reply_with_error ("parted output has no \"Number\" line"); > - return NULL; > } > - > - for (row = start; lines[row] != NULL; ++row) > - if (STREQ (lines[row], "")) { > - end = row; > - break; > - } > - > - if (end == 0) { > - reply_with_error ("parted output has no blank after end of table"); > - return NULL; > - } > - > - size_t nr_rows = end - start; > - > - r = malloc (sizeof *r); > - if (r == NULL) { > - reply_with_perror ("malloc"); > - return NULL; > - } > - r->guestfs_int_partition_list_len = nr_rows; > - r->guestfs_int_partition_list_val > - malloc (nr_rows * sizeof (guestfs_int_partition)); > - if (r->guestfs_int_partition_list_val == NULL) { > - reply_with_perror ("malloc"); > - goto error2; > - } > - > - /* Now parse the lines. */ > - size_t i; > + } else { > for (i = 0, row = start; row < end; ++i, ++row) { > if (sscanf (lines[row], " %d %" SCNi64 "B %" SCNi64 "B %" SCNi64 "B", > &r->guestfs_int_partition_list_val[i].part_num, > @@ -557,11 +555,18 @@ do_part_list (const char *device) > reply_with_error ("could not parse row from output of parted print command: %s", lines[row]); > goto error3; > } > + > + r->guestfs_int_partition_list_val[i].part_type = strdup(""); > + if (r->guestfs_int_partition_list_val[i].part_type == NULL) > + goto error4; > } > } > > return r; > > + error4: > + for (k = 0; k <= i; k++) > + free (r->guestfs_int_partition_list_val[k].part_type); > error3: > free (r->guestfs_int_partition_list_val); > error2: > diff --git a/generator/structs.ml b/generator/structs.ml > index ea110a1..e7a9fa6 100644 > --- a/generator/structs.ml > +++ b/generator/structs.ml > @@ -240,6 +240,7 @@ let structs = [ > "part_start", FBytes; > "part_end", FBytes; > "part_size", FBytes; > + "part_type", FString; > ]; > s_camel_name = "Partition" }; >I'd just add a new part_get_type (or something similar), which would call parted to return "primary"/etc. This would match what we do already with other attributes of partitions, and not force part_list to use a non-machine output type (which is not really meant for machine parsing).> diff --git a/resize/resize.ml b/resize/resize.ml > index 84fd6d4..8f8f67f 100644 > --- a/resize/resize.ml > +++ b/resize/resize.ml > @@ -1078,7 +1078,7 @@ read the man page virt-resize(1). > *) > p_name = ""; > p_part = { G.part_num = 0l; part_start = 0L; part_end = 0L; > - part_size = 0L }; > + part_size = 0L; part_type = "" }; > p_bootable = false; p_id = No_ID; p_type = ContentUnknown; > p_label = None; p_guid = None;Better add this information directly in the type partition, possibly also making use of type partition_type. Also this could go in a different patch than the above changes to get the primary/extended/etc type of a partition. Thanks, -- Pino Toscano
Chen, Hanxiao
2015-Mar-17 06:37 UTC
Re: [Libguestfs] [PATCH] part-list: add support for show partition type
> -----Original Message----- > From: libguestfs-bounces@redhat.com [mailto:libguestfs-bounces@redhat.com] On > Behalf Of Pino Toscano > Sent: Friday, March 13, 2015 6:32 PM > To: libguestfs@redhat.com > Subject: Re: [Libguestfs] [PATCH] part-list: add support for show partition type > > On Friday 13 March 2015 05:04:56 Chen Hanxiao wrote: > > We lack of showing parttition type for part-list command. > > This patch will add support for this. > > You cannot extend the struct returned by part_init with new members, > that will cause compatibility issues with existing C users of that API. > > > Also 'parted -m' did not provide partition type info, > > remove code section for 'parted -m' process. > > > > diff --git a/generator/structs.ml b/generator/structs.ml > > index ea110a1..e7a9fa6 100644 > > --- a/generator/structs.ml > > +++ b/generator/structs.ml > > @@ -240,6 +240,7 @@ let structs = [ > > "part_start", FBytes; > > "part_end", FBytes; > > "part_size", FBytes; > > + "part_type", FString; > > ]; > > s_camel_name = "Partition" }; > > > > I'd just add a new part_get_type (or something similar), which would > call parted to return "primary"/etc. This would match what we do > already with other attributes of partitions, and not force part_list > to use a non-machine output type (which is not really meant for > machine parsing).Alright. A new API would keep compatibility safe.> > > diff --git a/resize/resize.ml b/resize/resize.ml > > index 84fd6d4..8f8f67f 100644 > > --- a/resize/resize.ml > > +++ b/resize/resize.ml > > @@ -1078,7 +1078,7 @@ read the man page virt-resize(1). > > *) > > p_name = ""; > > p_part = { G.part_num = 0l; part_start = 0L; part_end = 0L; > > - part_size = 0L }; > > + part_size = 0L; part_type = "" }; > > p_bootable = false; p_id = No_ID; p_type = ContentUnknown; > > p_label = None; p_guid = None; > > Better add this information directly in the type partition, possibly > also making use of type partition_type. > > Also this could go in a different patch than the above changes to get > the primary/extended/etc type of a partition.I'll send a different patch for virt-resize on this. Regards, - Chen
Possibly Parallel Threads
- [PATCH] part-list: add support for show partition type
- [PATCH] Remove multiple hacks that only apply to RHEL 5.
- [PATCH 20/27] daemon: Reimplement ‘part_list’ API in OCaml.
- Re: [PATCH] New API: part_get_part_type for showing partition type
- Re: [PATCH] New API: part_get_part_type for showing partition type