From 8539b763639cbe80e4b248455c0c28bd8ced9cbe Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 28 Jun 2024 09:42:20 +0100 Subject: [PATCH] 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 c6c266a85d76dc2db90460202415790c585ac625 Fixes: https://issues.redhat.com/browse/RHEL-35998 (cherry picked from commit 24c1f7b03aab6343e6c826250269e98a6060d762) --- daemon/sfdisk.ml | 80 +++++++++++++++++++++++++++++++-------- generator/actions_core.ml | 4 +- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/daemon/sfdisk.ml b/daemon/sfdisk.ml index 2aea399aa..8c8ed2305 100644 --- a/daemon/sfdisk.ml +++ b/daemon/sfdisk.ml @@ -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 diff --git a/generator/actions_core.ml b/generator/actions_core.ml index 46ef1422f..ef9096772 100644 --- a/generator/actions_core.ml +++ b/generator/actions_core.ml @@ -8188,9 +8188,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 = "\ -- 2.43.0