mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
Add support for getting and setting GPT partition type GUIDs
New APIs: part_set_gpt_type part_get_gpt_type
This commit is contained in:
committed by
Richard W.M. Jones
parent
2aa731e7c4
commit
956e30effa
@@ -111,6 +111,7 @@ dosfstools
|
||||
file
|
||||
findutils
|
||||
gawk
|
||||
gdisk
|
||||
grep
|
||||
gzip
|
||||
jfsutils
|
||||
|
||||
125
daemon/parted.c
125
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,127 @@ 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 = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
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 *err = NULL;
|
||||
int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||||
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 (err);
|
||||
return NULL;
|
||||
}
|
||||
free (partnum_str);
|
||||
|
||||
char **lines = split_lines (err);
|
||||
if (lines == NULL) {
|
||||
reply_with_error ("'%s %s -i %i' returned no output",
|
||||
str_sgdisk, device, partnum);
|
||||
free (err);
|
||||
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;
|
||||
|
||||
/* 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");
|
||||
|
||||
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 (err);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
/* Ignore lines with no colon. Log to stderr so it will show up in
|
||||
* LIBGUESTFS_DEBUG. */
|
||||
if (verbose) {
|
||||
fprintf (stderr, "get-gpt-type: unexpected sgdisk output ignored: %s\n",
|
||||
line);
|
||||
}
|
||||
}
|
||||
}
|
||||
free (err);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -10692,6 +10692,37 @@ 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>. For MBR partitions,
|
||||
return an appropriate GUID corresponding to the MBR type. Behaviour is undefined
|
||||
for other partition types." };
|
||||
|
||||
]
|
||||
|
||||
(* Non-API meta-commands available only in guestfish.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -325,6 +325,11 @@ and test_init =
|
||||
*)
|
||||
| InitPartition
|
||||
|
||||
(* Identical to InitPartition, except that the partition table is GPT
|
||||
* instead of MBR.
|
||||
*)
|
||||
| InitGPT
|
||||
|
||||
(* /dev/sda contains a single partition /dev/sda1, which is formatted
|
||||
* as ext2, empty [except for lost+found] and mounted on /.
|
||||
* No LVM.
|
||||
|
||||
@@ -1 +1 @@
|
||||
391
|
||||
393
|
||||
|
||||
Reference in New Issue
Block a user