[Libguestfs] [PATCH] part-list: add support for show partition type

Pino Toscano ptoscano at redhat.com
Fri Mar 13 10:32:07 UTC 2015


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 at 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




More information about the Libguestfs mailing list