mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
daemon: Reimplement ‘part_list’ API in OCaml.
This commit is contained in:
@@ -383,62 +383,6 @@ do_part_get_parttype (const char *device)
|
||||
return r;
|
||||
}
|
||||
|
||||
guestfs_int_partition_list *
|
||||
do_part_list (const char *device)
|
||||
{
|
||||
CLEANUP_FREE char *out = print_partition_table (device, true);
|
||||
if (!out)
|
||||
return NULL;
|
||||
|
||||
CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);
|
||||
|
||||
if (!lines)
|
||||
return NULL;
|
||||
|
||||
guestfs_int_partition_list *r;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
for (i = 0, row = 2; lines[row] != NULL; ++i, ++row) {
|
||||
if (sscanf (lines[row], "%d:%" SCNi64 "B:%" SCNi64 "B:%" SCNi64 "B",
|
||||
&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) {
|
||||
reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
|
||||
goto error3;
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
|
||||
error3:
|
||||
free (r->guestfs_int_partition_list_val);
|
||||
error2:
|
||||
free (r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
do_part_get_bootable (const char *device, int partnum)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,8 @@ open Std_utils
|
||||
|
||||
open Utils
|
||||
|
||||
include Structs
|
||||
|
||||
(* Test if [sfdisk] is recent enough to have [--part-type], to be used
|
||||
* instead of [--print-id] and [--change-id].
|
||||
*)
|
||||
@@ -53,3 +55,57 @@ let part_get_mbr_id device partnum =
|
||||
|
||||
(* It's printed in hex, possibly with a leading space. *)
|
||||
sscanf out " %x" identity
|
||||
|
||||
(* This is not equivalent to print_partition_table in the C code, as
|
||||
* it only deals with the ‘-m’ option output, and it partially parses
|
||||
* that. If we convert other functions that don't use the ‘-m’ version
|
||||
* we'll have to refactor this. XXX
|
||||
*)
|
||||
let print_partition_table_machine_readable device =
|
||||
udev_settle ();
|
||||
|
||||
let args = ref [] in
|
||||
push_back args "-m";
|
||||
push_back args "-s";
|
||||
push_back args "--";
|
||||
push_back args device;
|
||||
push_back args "unit";
|
||||
push_back args "b";
|
||||
push_back args "print";
|
||||
|
||||
let out =
|
||||
try command "parted" !args
|
||||
with
|
||||
(* Translate "unrecognised disk label" into an errno code. *)
|
||||
Failure str when String.find str "unrecognised disk label" >= 0 ->
|
||||
raise (Unix.Unix_error (Unix.EINVAL, "parted", device ^ ": " ^ str)) in
|
||||
|
||||
udev_settle ();
|
||||
|
||||
(* Split the output into lines. *)
|
||||
let out = String.trim out in
|
||||
let lines = String.nsplit "\n" out in
|
||||
|
||||
(* lines[0] is "BYT;", lines[1] is the device line which we ignore,
|
||||
* lines[2..] are the partitions themselves.
|
||||
*)
|
||||
match lines with
|
||||
| "BYT;" :: _ :: lines -> lines
|
||||
| [] | [_] ->
|
||||
failwith "too few rows of output from 'parted print' command"
|
||||
| _ ->
|
||||
failwith "did not see 'BYT;' magic value in 'parted print' command"
|
||||
|
||||
let part_list device =
|
||||
let lines = print_partition_table_machine_readable device in
|
||||
|
||||
List.map (
|
||||
fun line ->
|
||||
try sscanf line "%d:%LdB:%LdB:%LdB"
|
||||
(fun num start end_ size ->
|
||||
{ part_num = Int32.of_int num;
|
||||
part_start = start; part_end = end_; part_size = size })
|
||||
with Scan_failure err ->
|
||||
failwithf "could not parse row from output of 'parted print' command: %s: %s"
|
||||
line err
|
||||
) lines
|
||||
|
||||
@@ -16,4 +16,12 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*)
|
||||
|
||||
type partition = {
|
||||
part_num : int32;
|
||||
part_start : int64;
|
||||
part_end : int64;
|
||||
part_size : int64;
|
||||
}
|
||||
|
||||
val part_get_mbr_id : string -> int -> int
|
||||
val part_list : string -> partition list
|
||||
|
||||
@@ -5039,6 +5039,7 @@ table. This works on C<gpt> but not on C<mbr> partitions." };
|
||||
{ defaults with
|
||||
name = "part_list"; added = (1, 0, 78);
|
||||
style = RStructList ("partitions", "partition"), [String (Device, "device")], [];
|
||||
impl = OCaml "Parted.part_list";
|
||||
tests = [] (* XXX Add a regression test for this. *);
|
||||
shortdesc = "list partitions on a device";
|
||||
longdesc = "\
|
||||
|
||||
Reference in New Issue
Block a user