daemon: Fix parsing in part_get_gpt_attributes

The actual output of sfdisk --part-attrs is bizarre and doesn't match
the documentation.  After looking at the source from util-linux, fix
the parsing to match what sfdisk produces.

Reported-by: Yongkui Guo
Fixes: commit c6c266a85d
Fixes: https://issues.redhat.com/browse/RHEL-35998
This commit is contained in:
Richard W.M. Jones
2024-06-28 09:42:20 +01:00
parent 882ef4d93a
commit 24c1f7b03a
2 changed files with 66 additions and 18 deletions

View File

@@ -114,28 +114,76 @@ let part_get_gpt_attributes device partnum =
command "sfdisk" ["--part-attrs"; device; string_of_int partnum] in
udev_settle ();
let out = String.trimr out in
(* The output is a whitespace-separated list of:
*
* "RequiredPartition" (equivalent to bit 0)
* "NoBlockIOProtocol" (equivalent to bit 1)
* "LegacyBIOSBootable" (equivalent to bit 2)
* "48", "49", ..., "63"
* "GUID:" followed by a comma-separated list of bit numbers
*
* eg: "LegacyBIOSBootable RequiredPartition GUID:48,49"
*
* So this is a massive PITA to parse.
*)
let out = String.trimr out in
let attrs = String.nsplit " " out in
List.fold_left (
fun bits attr ->
let rec loop out acc =
let len = String.length out in
eprintf "part_get_gpt_attributes: %S [%s]\n%!"
out (String.concat "," (List.map string_of_int acc));
if len = 0 then (
acc
)
else if Char.isspace out.[0] then (
let out = String.triml out in
loop out acc
)
else if out.[0] = ',' then (
let out = String.sub out 1 (len-1) in
loop out acc
)
else if String.is_prefix out "RequiredPartition" then (
let acc = 0 :: acc in
let out = String.sub out 17 (len-17) in
loop out acc
)
else if String.is_prefix out "NoBlockIOProtocol" then (
let acc = 1 :: acc in
let out = String.sub out 17 (len-17) in
loop out acc
)
else if String.is_prefix out "LegacyBIOSBootable" then (
let acc = 2 :: acc in
let out = String.sub out 18 (len-18) in
loop out acc
)
else if String.is_prefix out "GUID:" then (
let out = String.sub out 5 (len-5) in
loop out acc
)
else if Char.isdigit out.[0] then (
let n = String.span out "0123456789" in
let num, out = String.break n out in
let bit =
match attr with
| "" -> -1
| "RequiredPartition" -> 0
| "NoBlockIOProtocol" -> 1
| "LegacyBIOSBootable" -> 2
| n -> int_of_string n in
if bit >= 0 then
Int64.logor bits (Int64.shift_left 1_L bit)
else
bits
) 0_L attrs
try int_of_string num
with Failure _ ->
failwithf "part_get_gpt_attributes: cannot parse number %S" num in
let acc = bit :: acc in
loop out acc
)
else (
failwithf "part_get_gpt_attributes: cannot parse %S" out
)
in
let attrs = loop out [] in
let bits =
List.fold_left (
fun bits bit -> Int64.logor bits (Int64.shift_left 1_L bit)
) 0_L attrs in
eprintf "part_get_gpt_attributes: [%s] -> %Ld\n%!"
(String.concat "," (List.map string_of_int attrs)) bits;
bits
let part_set_gpt_attributes device partnum attrs =
if partnum <= 0 then

View File

@@ -8179,9 +8179,9 @@ for a useful list of partition attributes." };
tests = [
InitGPT, Always, TestResult (
[["part_set_gpt_attributes"; "/dev/sda"; "1";
"0"];
(* bits 0, 2, 48 and 49 set *) "844424930131973"];
["part_get_gpt_attributes"; "/dev/sda"; "1"]],
"ret == 0"), [];
"ret == 844424930131973"), [];
];
shortdesc = "get the attribute flags of a GPT partition";
longdesc = "\