mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
daemon: Reimplement 'part_get_mbr_part_type' API in OCaml.
Instead of parsing 'parted' output OCaml implementation relies on the following facts: 1. MBR partition table can hold up to 4 "primary" partitions. 2. Partition with number greater then 4 is "logical" partition. 3. Partition with number less then or equal to 4 with MBR ID 0x05 or 0x0f is "extended" partition (http://thestarman.pcministry.com/asm/mbr/PartTypes.htm; https://en.wikipedia.org/wiki/Partition_type) or "primary" otherwise.
This commit is contained in:
committed by
Richard W.M. Jones
parent
81d951239f
commit
994ca1f8eb
106
daemon/parted.c
106
daemon/parted.c
@@ -602,112 +602,6 @@ do_part_get_name (const char *device, int partnum)
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
do_part_get_mbr_part_type (const char *device, int partnum)
|
||||
{
|
||||
CLEANUP_FREE char *parttype;
|
||||
char *part_type;
|
||||
|
||||
parttype = do_part_get_parttype (device);
|
||||
if (parttype == NULL)
|
||||
return NULL;
|
||||
|
||||
/* machine parseable output by 'parted -m' did not provide
|
||||
* partition type info.
|
||||
* Use traditional style.
|
||||
*/
|
||||
CLEANUP_FREE char *out = print_partition_table (device, false);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);
|
||||
|
||||
if (!lines)
|
||||
return NULL;
|
||||
|
||||
size_t start = 0, end = 0, row;
|
||||
|
||||
for (row = 0; lines[row] != NULL; ++row)
|
||||
if (STRPREFIX (lines[row], "Number")) {
|
||||
start = row + 1;
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Now parse the lines. */
|
||||
size_t i;
|
||||
int64_t temp_int64;
|
||||
int part_num;
|
||||
char temp_type[16] = {'\0'};
|
||||
for (i = 0, row = start; row < end; ++i, ++row) {
|
||||
if (STREQ (parttype, "gpt")) {
|
||||
memcpy (temp_type, "primary", strlen ("primary"));
|
||||
if (sscanf (lines[row], "%d%" SCNi64 "B%" SCNi64 "B%" SCNi64 "B",
|
||||
&part_num,
|
||||
&temp_int64,
|
||||
&temp_int64,
|
||||
&temp_int64) != 4) {
|
||||
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if (sscanf (lines[row], "%d%" SCNi64 "B%" SCNi64 "B%" SCNi64 "B" "%15s",
|
||||
&part_num,
|
||||
&temp_int64,
|
||||
&temp_int64,
|
||||
&temp_int64,
|
||||
temp_type) != 5) {
|
||||
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (part_num != partnum)
|
||||
continue;
|
||||
|
||||
if (STRPREFIX (temp_type, "primary")) {
|
||||
part_type = strdup ("primary");
|
||||
if (part_type == NULL)
|
||||
goto error;
|
||||
} else if (STRPREFIX (temp_type, "logical")) {
|
||||
part_type = strdup ("logical");
|
||||
if (part_type == NULL)
|
||||
goto error;
|
||||
} else if (STRPREFIX (temp_type, "extended")) {
|
||||
part_type = strdup ("extended");
|
||||
if (part_type == NULL)
|
||||
goto error;
|
||||
} else
|
||||
goto error;
|
||||
|
||||
return part_type;
|
||||
}
|
||||
|
||||
if (row == end) {
|
||||
reply_with_error ("could not find partnum: %d", partnum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error:
|
||||
reply_with_error ("strdup failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
extract_uuid (const char *value)
|
||||
{
|
||||
|
||||
@@ -125,6 +125,19 @@ let part_get_parttype device =
|
||||
| _ ->
|
||||
failwithf "%s: cannot parse the output of parted" device
|
||||
|
||||
let part_get_mbr_part_type device partnum =
|
||||
let parttype = part_get_parttype device in
|
||||
let mbr_id = part_get_mbr_id device partnum in
|
||||
|
||||
(* 0x05 - extended partition.
|
||||
* 0x0f - extended partition using BIOS INT 13h extensions.
|
||||
*)
|
||||
match parttype, partnum, mbr_id with
|
||||
| "msdos", (1|2|3|4), (0x05|0x0f) -> "extended"
|
||||
| "msdos", (1|2|3|4), _ -> "primary"
|
||||
| "msdos", _, _ -> "logical"
|
||||
| _, _, _ -> "primary"
|
||||
|
||||
let part_set_gpt_attributes device partnum attributes =
|
||||
if partnum <= 0 then failwith "partition number must be >= 1";
|
||||
|
||||
|
||||
@@ -9213,6 +9213,7 @@ All data will be zeroed, but metadata and the like is preserved." };
|
||||
{ defaults with
|
||||
name = "part_get_mbr_part_type"; added = (1, 29, 32);
|
||||
style = RString (RPlainString, "partitiontype"), [String (Device, "device"); Int "partnum"], [];
|
||||
impl = OCaml "Parted.part_get_mbr_part_type";
|
||||
tests = [
|
||||
InitEmpty, Always, TestResultString (
|
||||
[["part_init"; "/dev/sda"; "mbr"];
|
||||
|
||||
Reference in New Issue
Block a user