Instead of parsing 'parted' output OCaml implementation relies on the following facts:
1. The function is applicable for MBR partitions only (as noted in documentation and as function name suggests). 2. An attempt to call the function for non-MBR partition fails with "part_get_mbr_part_type can only be used on MBR Partitions" error and NULL is returned. 3. MBR partition table can hold up to 4 "primary" partitions. 4. Partition with number >= 5 is logical partition 5. Extnded partition number is <= 4 and has MBR id 0x05 or 0x0f (http://thestarman.pcministry.com/asm/mbr/PartTypes.htm; https://en.wikipedia.org/wiki/Partition_type). --- daemon/parted.c | 106 ---------------------------------------------- daemon/parted.ml | 14 ++++++ daemon/parted.mli | 2 + generator/actions_core.ml | 1 + 4 files changed, 17 insertions(+), 106 deletions(-) diff --git a/daemon/parted.c b/daemon/parted.c index e5435b5..d67c6c5 100644 --- a/daemon/parted.c +++ b/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) { diff --git a/daemon/parted.ml b/daemon/parted.ml index ce8da8a..75d9d37 100644 --- a/daemon/parted.ml +++ b/daemon/parted.ml @@ -125,6 +125,20 @@ 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 id within the first 1024 cylinders. + * 0x0f - extended partition id beyond the first 1024 cylinders. + *) + match parttype, partnum, mbr_id with + | "msdos", (1|2|3|4), (0x05|0x0f) -> "extended" + | "msdos", (1|2|3|4), _ -> "primary" + | "msdos", _, _ -> "logical" + | _, _, _ -> + failwithf "part_get_mbr_part_type can only be used on MBR Partitions" + let part_set_gpt_attributes device partnum attributes = if partnum <= 0 then failwith "partition number must be >= 1"; diff --git a/daemon/parted.mli b/daemon/parted.mli index d547f2f..0f59d29 100644 --- a/daemon/parted.mli +++ b/daemon/parted.mli @@ -28,6 +28,8 @@ val part_list : string -> partition list val part_get_parttype : string -> string +val part_get_mbr_part_type : string -> int -> string + val part_get_gpt_type : string -> int -> string val part_get_gpt_guid : string -> int -> string val part_get_gpt_attributes : string -> int -> int64 diff --git a/generator/actions_core.ml b/generator/actions_core.ml index 544cb6e..307e414 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -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"]; -- 2.9.5 _______________________________________________ Libguestfs mailing list Libguestfs@redhat.com https://www.redhat.com/mailman/listinfo/libguestfs