Matthew Booth
2012-Dec-14 13:54 UTC
[Libguestfs] [PATCH] Add support for getting and setting GPT partition type GUIDs
New APIs: part_set_gpt_type part_get_gpt_type --- appliance/packagelist.in | 1 + daemon/parted.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ generator/actions.ml | 30 +++++++++++ generator/tests_c_api.ml | 7 +++ generator/types.ml | 5 ++ src/MAX_PROC_NR | 2 +- 6 files changed, 173 insertions(+), 1 deletion(-) diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 3ad343b..9b0cc09 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -111,6 +111,7 @@ dosfstools file findutils gawk +gdisk grep gzip jfsutils diff --git a/daemon/parted.c b/daemon/parted.c index cc9a84b..01ae91c 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -30,6 +30,7 @@ GUESTFSD_EXT_CMD(str_parted, parted); GUESTFSD_EXT_CMD(str_sfdisk, sfdisk); +GUESTFSD_EXT_CMD(str_sgdisk, sgdisk); /* Notes: * @@ -802,3 +803,131 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte) return 0; } + +int +do_part_set_gpt_type(const char *device, int partnum, const char *guid) +{ + if (partnum <= 0) { + reply_with_error ("partition number must be >= 1"); + return -1; + } + + char *typecode = NULL; + if (asprintf (&typecode, "%i:%s", partnum, guid) == -1) { + reply_with_perror ("asprintf"); + return -1; + } + + char *err = NULL; + int r = command (NULL, &err, str_sgdisk, device, "-t", typecode, NULL); + + if (r == -1) { + reply_with_error ("%s %s -t %s: %s", str_sgdisk, device, typecode, err); + free (typecode); + free (err); + return -1; + } + free (typecode); + free (err); + + return 0; +} + +char * +do_part_get_gpt_type(const char *device, int partnum) +{ + if (partnum <= 0) { + reply_with_error ("partition number must be >= 1"); + return NULL; + } + + char *partnum_str = NULL; + if (asprintf (&partnum_str, "%i", partnum) == -1) { + reply_with_perror ("asprintf"); + return NULL; + } + + char *out = NULL, *err = NULL; + int r = command (&out, &err, str_sgdisk, device, "-i", partnum_str, NULL); + + if (r == -1) { + reply_with_error ("%s %s -i %s: %s", str_sgdisk, device, partnum_str, err); + free (partnum_str); + free (out); + free (err); + return NULL; + } + free (partnum_str); + free (err); + + if (verbose) + fprintf (stderr, "Output of %s %s -i %i:\n", str_sgdisk, device, partnum); + + char **lines = split_lines (out); + if (lines == NULL) { + reply_with_error ("'%s %s -i %i' returned no output", + str_sgdisk, device, partnum); + free (out); + return NULL; + } + + /* Parse the output of sgdisk -i: + * Partition GUID code: 21686148-6449-6E6F-744E-656564454649 (BIOS boot partition) + * Partition unique GUID: 19AEC5FE-D63A-4A15-9D37-6FCBFB873DC0 + * First sector: 2048 (at 1024.0 KiB) + * Last sector: 411647 (at 201.0 MiB) + * Partition size: 409600 sectors (200.0 MiB) + * Attribute flags: 0000000000000000 + * Partition name: 'EFI System Partition' + */ + for (char **i = lines; *i != NULL; i++) { + char *line = *i; + + if (verbose) fprintf (stderr, "%s\n", line); + + /* Skip blank lines */ + if (line[0] == '\0') continue; + + /* Split the line in 2 at the colon */ + char *colon = strchr (line, ':'); + if (colon) { +#define SEARCH "Partition GUID code" + if (colon - line == strlen(SEARCH) && + memcmp (line, SEARCH, strlen(SEARCH)) == 0) + { +#undef SEARCH + /* The value starts after the colon */ + char *value = colon + 1; + + /* Skip any leading whitespace */ + value += strspn (value, " \t"); + + /* The value contains only valid GUID characters */ + size_t value_len = strspn (value, "-0123456789ABCDEF"); +fprintf(stderr, "%zi: %s\n", value_len, value); + + char *ret = malloc (value_len + 1); + if (ret == NULL) { + reply_with_perror ("malloc"); + return NULL; + } + + memcpy (ret, value, value_len); + ret[value_len] = '\0'; + free (out); + return ret; + } + } else { + /* Ignore lines with no colon. Log to stderr so it will show up in + * LIBGUESTFS_DEBUG. */ + fprintf (stderr, "get-gpt-type: unexpected sgdisk output ignored: %s", + line); + } + } + free (out); + + /* If we got here it means we didn't find the Partition GUID code */ + reply_with_error ("sgdisk output did not contain Partition GUID code. " + "See LIBGUESTFS_DEBUG output for more details"); + return NULL; +} diff --git a/generator/actions.ml b/generator/actions.ml index f78d851..d8ec323 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -10692,6 +10692,36 @@ not always, the name of a Windows drive, eg. C<E:>." }; Return the list of partitions in the volume named C<volume> in the disk group with GUID <diskgroup>." }; + { defaults with + name = "part_set_gpt_type"; + style = RErr, [Device "device"; Int "partnum"; String "guid"], []; + proc_nr = Some 392; + tests = []; + shortdesc = "set the type GUID of a GPT partition"; + longdesc = "\ +Set the type GUID of numbered GPT partition C<partnum> to C<guid>. Return an +error if the partition table of C<device> isn't GPT, or if C<guid> is not a +valid GUID. + +See L<http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_type_GUIDs> +for a useful list of type GUIDs." }; + + { defaults with + name = "part_get_gpt_type"; + style = RString "guid", [Device "device"; Int "partnum"], []; + proc_nr = Some 393; + tests = [ + InitGPT, Always, TestOutput ( + [["part_set_gpt_type"; "/dev/sda"; "1"; + "01234567-89AB-CDEF-0123-456789ABCDEF"]; + ["part_get_gpt_type"; "/dev/sda"; "1"]], + "01234567-89AB-CDEF-0123-456789ABCDEF"); + ]; + shortdesc = "get the type GUID of a GPT partition"; + longdesc = "\ +Return the type GUID of numbered GPT partition C<partnum>. Return an error if +the partition table of C<device> isn't GPT." }; + ] (* Non-API meta-commands available only in guestfish. diff --git a/generator/tests_c_api.ml b/generator/tests_c_api.ml index 116a8b0..2aa78df 100644 --- a/generator/tests_c_api.ml +++ b/generator/tests_c_api.ml @@ -442,6 +442,13 @@ and generate_one_test_body name i test_name init test ["umount_all"]; ["lvm_remove_all"]; ["part_disk"; "/dev/sda"; "mbr"]] + | InitGPT -> + pr " /* InitGPT for %s: create /dev/sda1 */\n" test_name; + List.iter (generate_test_command_call test_name) + [["blockdev_setrw"; "/dev/sda"]; + ["umount_all"]; + ["lvm_remove_all"]; + ["part_disk"; "/dev/sda"; "gpt"]] | InitBasicFS -> pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name; List.iter (generate_test_command_call test_name) diff --git a/generator/types.ml b/generator/types.ml index cff3c6d..a2e3307 100644 --- a/generator/types.ml +++ b/generator/types.ml @@ -332,6 +332,11 @@ and test_init * Note: for testing filesystem operations, it is quicker to use * InitScratchFS *) + | InitGPT + + (* Identical to InitPartition, except that the partition table is GPT + * instead of MBR. + *) | InitBasicFS (* /dev/sda: diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index b570ddb..25685cf 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -391 +393 -- 1.7.11.7
Richard W.M. Jones
2012-Dec-14 15:12 UTC
[Libguestfs] [PATCH] Add support for getting and setting GPT partition type GUIDs
On Fri, Dec 14, 2012 at 01:54:24PM +0000, Matthew Booth wrote:> diff --git a/generator/types.ml b/generator/types.ml > index cff3c6d..a2e3307 100644 > --- a/generator/types.ml > +++ b/generator/types.ml > @@ -332,6 +332,11 @@ and test_init > * Note: for testing filesystem operations, it is quicker to use > * InitScratchFS > *) > + | InitGPT > + > + (* Identical to InitPartition, except that the partition table is GPT > + * instead of MBR. > + *) > | InitBasicFS > > (* /dev/sda:This comment is in the wrong place isn't it? ACK with that fixed, if necessary. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming blog: http://rwmj.wordpress.com Fedora now supports 80 OCaml packages (the OPEN alternative to F#) http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora
Apparently Analagous Threads
- [PATCH v2] daemon: Remove GUESTFSD_EXT_CMD.
- [PATCH 2/2] daemon: Replace GUESTFSD_EXT_CMD with --print-external-commands.
- [PATCHv2 1/3] New API: part_get_disk_guid and part_set_disk_guid.
- [PATCH] New API: part_get_disk_guid and part_set_disk_guid.
- [PATCH 2/3] New APIs: part_set_gpt_attributes and part_get_gpt_attributes