658 lines
21 KiB
Diff
658 lines
21 KiB
Diff
|
From 15cc88b3cbc810a7d832af8f1046c71cc6e51118 Mon Sep 17 00:00:00 2001
|
||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||
|
Date: Fri, 10 May 2024 13:27:22 +0100
|
||
|
Subject: [PATCH] daemon: Reimplement partition GPT functions using sfdisk
|
||
|
|
||
|
sfdisk can now do everything with GPT that sgdisk was needed for
|
||
|
before. In particular we are able to reimplement the following
|
||
|
functions using sfdisk:
|
||
|
|
||
|
- part_set_disk_guid (replace with sfdisk --disk-id)
|
||
|
- part_get_disk_guid
|
||
|
- part_set_disk_guid_random
|
||
|
- part_set_gpt_attributes (sfdisk --part-attrs)
|
||
|
- part_get_gpt_attributes
|
||
|
- part_set_gpt_guid (sfdisk --part-uuid)
|
||
|
- part_get_gpt_guid
|
||
|
- part_set_gpt_type (sfdisk --part-type)
|
||
|
- part_get_gpt_type
|
||
|
|
||
|
This allows us to drop the requirement for gdisk in many cases.
|
||
|
|
||
|
There is only one API remaining which requires gdisk, part_expand_gpt,
|
||
|
which we do not use in our tools. In a prior commit I already moved
|
||
|
this solitary function to a new source file (daemon/gdisk.c).
|
||
|
|
||
|
Fixes: https://issues.redhat.com/browse/RHEL-35998
|
||
|
(cherry picked from commit c6c266a85d76dc2db90460202415790c585ac625)
|
||
|
---
|
||
|
.gitignore | 1 +
|
||
|
daemon/Makefile.am | 3 +
|
||
|
daemon/inspect_fs_windows.ml | 2 +-
|
||
|
daemon/listfs.ml | 2 +-
|
||
|
daemon/parted.c | 144 -----------------------------
|
||
|
daemon/parted.ml | 92 +------------------
|
||
|
daemon/sfdisk.ml | 172 +++++++++++++++++++++++++++++++++++
|
||
|
generator/actions_core.ml | 24 ++---
|
||
|
8 files changed, 189 insertions(+), 251 deletions(-)
|
||
|
create mode 100644 daemon/sfdisk.ml
|
||
|
|
||
|
diff --git a/.gitignore b/.gitignore
|
||
|
index 00e59fb37..2fc52e843 100644
|
||
|
--- a/.gitignore
|
||
|
+++ b/.gitignore
|
||
|
@@ -108,6 +108,7 @@ Makefile.in
|
||
|
/daemon/parted.mli
|
||
|
/daemon/realpath.mli
|
||
|
/daemon/rpm.mli
|
||
|
+/daemon/sfdisk.mli
|
||
|
/daemon/stamp-guestfsd.pod
|
||
|
/daemon/statvfs.mli
|
||
|
/daemon/structs-cleanups.c
|
||
|
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
|
||
|
index 04370b7cd..bc74b6ef7 100644
|
||
|
--- a/daemon/Makefile.am
|
||
|
+++ b/daemon/Makefile.am
|
||
|
@@ -59,6 +59,7 @@ generator_built = \
|
||
|
parted.mli \
|
||
|
realpath.mli \
|
||
|
rpm.mli \
|
||
|
+ sfdisk.mli \
|
||
|
statvfs.mli \
|
||
|
structs.ml \
|
||
|
structs.mli
|
||
|
@@ -306,6 +307,7 @@ SOURCES_MLI = \
|
||
|
parted.mli \
|
||
|
realpath.mli \
|
||
|
rpm.mli \
|
||
|
+ sfdisk.mli \
|
||
|
statvfs.mli \
|
||
|
structs.mli \
|
||
|
sysroot.mli \
|
||
|
@@ -337,6 +339,7 @@ SOURCES_ML = \
|
||
|
md.ml \
|
||
|
mount.ml \
|
||
|
mount_utils.ml \
|
||
|
+ sfdisk.ml \
|
||
|
parted.ml \
|
||
|
listfs.ml \
|
||
|
realpath.ml \
|
||
|
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
|
||
|
index 5d29c3a46..6537481e1 100644
|
||
|
--- a/daemon/inspect_fs_windows.ml
|
||
|
+++ b/daemon/inspect_fs_windows.ml
|
||
|
@@ -419,7 +419,7 @@ and map_registry_disk_blob_gpt partitions blob =
|
||
|
let typ = Parted.part_get_parttype device in
|
||
|
if typ <> "gpt" then false
|
||
|
else (
|
||
|
- let guid = Parted.part_get_gpt_guid device partnum in
|
||
|
+ let guid = Sfdisk.part_get_gpt_guid device partnum in
|
||
|
String.lowercase_ascii guid = blob_guid
|
||
|
)
|
||
|
) partitions in
|
||
|
diff --git a/daemon/listfs.ml b/daemon/listfs.ml
|
||
|
index 4cc3c437a..93c1e7145 100644
|
||
|
--- a/daemon/listfs.ml
|
||
|
+++ b/daemon/listfs.ml
|
||
|
@@ -114,7 +114,7 @@ and is_partition_can_hold_filesystem partition =
|
||
|
else if is_mbr then
|
||
|
true
|
||
|
else (
|
||
|
- let gpt_type = Parted.part_get_gpt_type device partnum in
|
||
|
+ let gpt_type = Sfdisk.part_get_gpt_type device partnum in
|
||
|
match gpt_type with
|
||
|
(* Windows Logical Disk Manager metadata partition. *)
|
||
|
| "5808C8AA-7E8F-42E0-85D2-E1E90434CFB3"
|
||
|
diff --git a/daemon/parted.c b/daemon/parted.c
|
||
|
index 9af5556c9..0f19baae5 100644
|
||
|
--- a/daemon/parted.c
|
||
|
+++ b/daemon/parted.c
|
||
|
@@ -456,58 +456,6 @@ do_part_set_mbr_id (const char *device, int partnum, int idbyte)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-int
|
||
|
-do_part_set_gpt_type (const char *device, int partnum, const char *guid)
|
||
|
-{
|
||
|
- if (partnum <= 0) {
|
||
|
- reply_with_error ("partition number must be >= 1");
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- CLEANUP_FREE char *typecode = NULL;
|
||
|
- if (asprintf (&typecode, "%i:%s", partnum, guid) == -1) {
|
||
|
- reply_with_perror ("asprintf");
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- CLEANUP_FREE char *err = NULL;
|
||
|
- int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||
|
- "sgdisk", device, "-t", typecode, NULL);
|
||
|
-
|
||
|
- if (r == -1) {
|
||
|
- reply_with_error ("%s %s -t %s: %s", "sgdisk", device, typecode, err);
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int
|
||
|
-do_part_set_gpt_guid (const char *device, int partnum, const char *guid)
|
||
|
-{
|
||
|
- if (partnum <= 0) {
|
||
|
- reply_with_error ("partition number must be >= 1");
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- CLEANUP_FREE char *typecode = NULL;
|
||
|
- if (asprintf (&typecode, "%i:%s", partnum, guid) == -1) {
|
||
|
- reply_with_perror ("asprintf");
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- CLEANUP_FREE char *err = NULL;
|
||
|
- int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||
|
- "sgdisk", device, "-u", typecode, NULL);
|
||
|
-
|
||
|
- if (r == -1) {
|
||
|
- reply_with_error ("%s %s -u %s: %s", "sgdisk", device, typecode, err);
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
char *
|
||
|
do_part_get_name (const char *device, int partnum)
|
||
|
{
|
||
|
@@ -564,95 +512,3 @@ do_part_get_name (const char *device, int partnum)
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
-
|
||
|
-static char *
|
||
|
-extract_uuid (const char *value)
|
||
|
-{
|
||
|
- /* The value contains only valid GUID characters */
|
||
|
- const size_t value_len = strspn (value, "-0123456789ABCDEF");
|
||
|
-
|
||
|
- char *ret = malloc (value_len + 1);
|
||
|
- if (ret == NULL) {
|
||
|
- reply_with_perror ("malloc");
|
||
|
- return NULL;
|
||
|
- }
|
||
|
-
|
||
|
- memcpy (ret, value, value_len);
|
||
|
- ret[value_len] = '\0';
|
||
|
- return ret;
|
||
|
-}
|
||
|
-
|
||
|
-char *
|
||
|
-do_part_get_disk_guid (const char *device)
|
||
|
-{
|
||
|
- const char *pattern = "Disk identifier (GUID):";
|
||
|
- size_t i;
|
||
|
-
|
||
|
- CLEANUP_FREE char *err = NULL;
|
||
|
- int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||
|
- "sgdisk", device, "-p", NULL);
|
||
|
- if (r == -1) {
|
||
|
- reply_with_error ("%s %s -p: %s", "sgdisk", device, err);
|
||
|
- return NULL;
|
||
|
- }
|
||
|
-
|
||
|
- CLEANUP_FREE_STRING_LIST char **lines = split_lines (err);
|
||
|
- if (lines == NULL) {
|
||
|
- reply_with_error ("'%s %s -p' returned no output",
|
||
|
- "sgdisk", device);
|
||
|
- return NULL;
|
||
|
- }
|
||
|
-
|
||
|
- for (i = 0; lines[i] != NULL; ++i) {
|
||
|
- if (STRPREFIX (lines[i], pattern)) {
|
||
|
- char *value = lines[i] + strlen (pattern);
|
||
|
-
|
||
|
- /* Skip any leading whitespace */
|
||
|
- value += strspn (value, " \t");
|
||
|
-
|
||
|
- /* Extract the actual information from the field. */
|
||
|
- char *ret = extract_uuid (value);
|
||
|
- if (ret == NULL) {
|
||
|
- /* The extraction function already sends the error. */
|
||
|
- return NULL;
|
||
|
- }
|
||
|
-
|
||
|
- return ret;
|
||
|
- }
|
||
|
- }
|
||
|
-
|
||
|
- /* If we got here it means we didn't find the field */
|
||
|
- reply_with_error ("sgdisk output did not contain disk GUID. "
|
||
|
- "See LIBGUESTFS_DEBUG output for more details");
|
||
|
- return NULL;
|
||
|
-}
|
||
|
-
|
||
|
-int
|
||
|
-do_part_set_disk_guid (const char *device, const char *guid)
|
||
|
-{
|
||
|
- CLEANUP_FREE char *err = NULL;
|
||
|
- int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||
|
- "sgdisk", device, "-U", guid, NULL);
|
||
|
-
|
||
|
- if (r == -1) {
|
||
|
- reply_with_error ("%s %s -U %s: %s", "sgdisk", device, guid, err);
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-int
|
||
|
-do_part_set_disk_guid_random (const char *device)
|
||
|
-{
|
||
|
- CLEANUP_FREE char *err = NULL;
|
||
|
- int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
|
||
|
- "sgdisk", device, "-U", "R", NULL);
|
||
|
-
|
||
|
- if (r == -1) {
|
||
|
- reply_with_error ("%s %s -U R: %s", "sgdisk", device, err);
|
||
|
- return -1;
|
||
|
- }
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
diff --git a/daemon/parted.ml b/daemon/parted.ml
|
||
|
index c9e55890b..f8f142bc5 100644
|
||
|
--- a/daemon/parted.ml
|
||
|
+++ b/daemon/parted.ml
|
||
|
@@ -25,18 +25,6 @@ open Utils
|
||
|
|
||
|
include Structs
|
||
|
|
||
|
-let part_get_mbr_id device partnum =
|
||
|
- if partnum <= 0 then
|
||
|
- failwith "partition number must be >= 1";
|
||
|
-
|
||
|
- udev_settle ();
|
||
|
- let out =
|
||
|
- command "sfdisk" ["--part-type"; device; string_of_int partnum] in
|
||
|
- udev_settle ();
|
||
|
-
|
||
|
- (* It's printed in hex, possibly with a leading space. *)
|
||
|
- sscanf out " %x" identity
|
||
|
-
|
||
|
(* This is almost equivalent to print_partition_table in the C code. The
|
||
|
* difference is that here we enforce the "BYT;" header internally.
|
||
|
*)
|
||
|
@@ -110,7 +98,7 @@ let part_get_parttype 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
|
||
|
+ let mbr_id = Sfdisk.part_get_mbr_id device partnum in
|
||
|
|
||
|
(* 0x05 - extended partition.
|
||
|
* 0x0f - extended partition using BIOS INT 13h extensions.
|
||
|
@@ -120,81 +108,3 @@ let part_get_mbr_part_type device partnum =
|
||
|
| "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";
|
||
|
-
|
||
|
- udev_settle ();
|
||
|
-
|
||
|
- let arg = sprintf "%d:=:%LX" partnum attributes in
|
||
|
- let r, _, err =
|
||
|
- commandr ~fold_stdout_on_stderr:true
|
||
|
- "sgdisk" [ device; "-A"; arg ] in
|
||
|
- if r <> 0 then
|
||
|
- failwithf "sgdisk: %s" err;
|
||
|
-
|
||
|
- udev_settle ()
|
||
|
-
|
||
|
-let extract_guid value =
|
||
|
- (* The value contains only valid GUID characters. *)
|
||
|
- String.sub value 0 (String.span value "-0123456789ABCDEF")
|
||
|
-
|
||
|
-let extract_hex value =
|
||
|
- (* The value contains only valid numeric characters. *)
|
||
|
- let str = String.sub value 0 (String.span value "0123456789ABCDEF") in
|
||
|
- Int64.of_string ("0x" ^ str)
|
||
|
-
|
||
|
-let sgdisk_info_extract_field device partnum field extractor =
|
||
|
- if partnum <= 0 then failwith "partition number must be >= 1";
|
||
|
-
|
||
|
- udev_settle ();
|
||
|
-
|
||
|
- let r, _, err =
|
||
|
- commandr ~fold_stdout_on_stderr:true
|
||
|
- "sgdisk" [ device; "-i"; string_of_int partnum ] in
|
||
|
- if r <> 0 then
|
||
|
- failwithf "getting %S: sgdisk: %s" field err;
|
||
|
-
|
||
|
- udev_settle ();
|
||
|
-
|
||
|
- let err = String.trim err in
|
||
|
- let lines = String.nsplit "\n" err in
|
||
|
-
|
||
|
- (* Parse the output of sgdisk -i:
|
||
|
- * Partition GUID code: 21686148-6449-6E6F-744E-656564454649 (BIOS boot partition)
|
||
|
- * Partition unique GUID: 19AEC5FE-D63A-4A15-9D37-6FCBFB873DC0
|
||
|
- * First sector: 2048 (at 1024.0 KiB)
|
||
|
- * Last sector: 411647 (at 201.0 MiB)
|
||
|
- * Partition size: 409600 sectors (200.0 MiB)
|
||
|
- * Attribute flags: 0000000000000000
|
||
|
- * Partition name: 'EFI System Partition'
|
||
|
- *)
|
||
|
- let field_len = String.length field in
|
||
|
- let rec loop = function
|
||
|
- | [] ->
|
||
|
- failwithf "%s: sgdisk output did not contain '%s'" device field
|
||
|
- | line :: _ when String.is_prefix line field &&
|
||
|
- String.length line >= field_len + 2 &&
|
||
|
- line.[field_len] = ':' ->
|
||
|
- let value =
|
||
|
- String.sub line (field_len+1) (String.length line - field_len - 1) in
|
||
|
-
|
||
|
- (* Skip any whitespace after the colon. *)
|
||
|
- let value = String.triml value in
|
||
|
-
|
||
|
- (* Extract the value. *)
|
||
|
- extractor value
|
||
|
-
|
||
|
- | _ :: lines -> loop lines
|
||
|
- in
|
||
|
- loop lines
|
||
|
-
|
||
|
-let rec part_get_gpt_type device partnum =
|
||
|
- sgdisk_info_extract_field device partnum "Partition GUID code"
|
||
|
- extract_guid
|
||
|
-and part_get_gpt_guid device partnum =
|
||
|
- sgdisk_info_extract_field device partnum "Partition unique GUID"
|
||
|
- extract_guid
|
||
|
-and part_get_gpt_attributes device partnum =
|
||
|
- sgdisk_info_extract_field device partnum "Attribute flags"
|
||
|
- extract_hex
|
||
|
diff --git a/daemon/sfdisk.ml b/daemon/sfdisk.ml
|
||
|
new file mode 100644
|
||
|
index 000000000..2aea399aa
|
||
|
--- /dev/null
|
||
|
+++ b/daemon/sfdisk.ml
|
||
|
@@ -0,0 +1,172 @@
|
||
|
+(* guestfs-inspection
|
||
|
+ * Copyright (C) 2009-2023 Red Hat Inc.
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation; either version 2 of the License, or
|
||
|
+ * (at your option) any later version.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
||
|
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||
|
+ *)
|
||
|
+
|
||
|
+open Scanf
|
||
|
+open Printf
|
||
|
+
|
||
|
+open Std_utils
|
||
|
+
|
||
|
+open Utils
|
||
|
+
|
||
|
+include Structs
|
||
|
+
|
||
|
+let part_get_mbr_id device partnum =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let out =
|
||
|
+ command "sfdisk" ["--part-type"; device; string_of_int partnum] in
|
||
|
+ udev_settle ();
|
||
|
+
|
||
|
+ (* It's printed in hex, possibly with a leading space. *)
|
||
|
+ sscanf out " %x" identity
|
||
|
+
|
||
|
+let part_get_gpt_type device partnum =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let out =
|
||
|
+ command "sfdisk" ["--part-type"; device; string_of_int partnum] in
|
||
|
+ udev_settle ();
|
||
|
+
|
||
|
+ String.trimr out
|
||
|
+
|
||
|
+let part_set_gpt_type device partnum typ =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let cmd =
|
||
|
+ sprintf "sfdisk --part-type %s %d %s"
|
||
|
+ (quote device) partnum (quote typ) in
|
||
|
+ if verbose () then eprintf "%s\n%!" cmd;
|
||
|
+ if Sys.command cmd <> 0 then failwith "sfdisk --part-type failed";
|
||
|
+ udev_settle ()
|
||
|
+
|
||
|
+let part_get_gpt_guid device partnum =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let out =
|
||
|
+ command "sfdisk" ["--part-uuid"; device; string_of_int partnum] in
|
||
|
+ udev_settle ();
|
||
|
+
|
||
|
+ String.trimr out
|
||
|
+
|
||
|
+let part_set_gpt_guid device partnum guid =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let cmd =
|
||
|
+ sprintf "sfdisk --part-uuid %s %d %s"
|
||
|
+ (quote device) partnum (quote guid) in
|
||
|
+ if verbose () then eprintf "%s\n%!" cmd;
|
||
|
+ if Sys.command cmd <> 0 then failwith "sfdisk --part-uuid failed";
|
||
|
+ udev_settle ()
|
||
|
+
|
||
|
+let part_get_disk_guid device =
|
||
|
+ udev_settle ();
|
||
|
+ let out =
|
||
|
+ command "sfdisk" ["--disk-id"; device] in
|
||
|
+ udev_settle ();
|
||
|
+
|
||
|
+ String.trimr out
|
||
|
+
|
||
|
+let part_set_disk_guid device guid =
|
||
|
+ udev_settle ();
|
||
|
+ let cmd =
|
||
|
+ sprintf "sfdisk --disk-id %s %s"
|
||
|
+ (quote device) (quote guid) in
|
||
|
+ if verbose () then eprintf "%s\n%!" cmd;
|
||
|
+ if Sys.command cmd <> 0 then failwith "sfdisk --disk-id failed";
|
||
|
+ udev_settle ()
|
||
|
+
|
||
|
+let part_set_disk_guid_random device =
|
||
|
+ let random_uuid = Utils.get_random_uuid () in
|
||
|
+ let random_uuid = String.trimr random_uuid in
|
||
|
+ part_set_disk_guid device random_uuid
|
||
|
+
|
||
|
+let part_get_gpt_attributes device partnum =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let out =
|
||
|
+ command "sfdisk" ["--part-attrs"; device; string_of_int partnum] in
|
||
|
+ udev_settle ();
|
||
|
+
|
||
|
+ (* 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"
|
||
|
+ *)
|
||
|
+ let out = String.trimr out in
|
||
|
+ let attrs = String.nsplit " " out in
|
||
|
+ List.fold_left (
|
||
|
+ fun bits attr ->
|
||
|
+ 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
|
||
|
+
|
||
|
+let part_set_gpt_attributes device partnum attrs =
|
||
|
+ if partnum <= 0 then
|
||
|
+ failwith "partition number must be >= 1";
|
||
|
+
|
||
|
+ (* The input to sfdisk --part-attrs is a comma-separated list of
|
||
|
+ * attribute names or bit positions. Note you have to use the
|
||
|
+ * names, you can't use "0", "1" or "2".
|
||
|
+ *)
|
||
|
+ let s = ref [] in
|
||
|
+ let rec loop i =
|
||
|
+ let b = Int64.logand attrs (Int64.shift_left 1_L i) <> Int64.zero in
|
||
|
+ (match i with
|
||
|
+ | 0 -> if b then List.push_front "RequiredPartition" s
|
||
|
+ | 1 -> if b then List.push_front "NoBlockIOProtocol" s
|
||
|
+ | 2 -> if b then List.push_front "LegacyBIOSBootable" s
|
||
|
+ | i when i >= 3 && i <= 47 ->
|
||
|
+ if b then
|
||
|
+ failwith "bits 3..47 are reserved and cannot be set"
|
||
|
+ | i when i >= 48 && i <= 63 ->
|
||
|
+ if b then List.push_front (string_of_int i) s
|
||
|
+ | _ -> assert false
|
||
|
+ );
|
||
|
+ if i < 63 then loop (i+1)
|
||
|
+ in
|
||
|
+ loop 0;
|
||
|
+
|
||
|
+ udev_settle ();
|
||
|
+ let cmd =
|
||
|
+ sprintf "sfdisk --part-attrs %s %d %s"
|
||
|
+ (quote device) partnum (quote (String.concat "," !s)) in
|
||
|
+ if verbose () then eprintf "%s\n%!" cmd;
|
||
|
+ if Sys.command cmd <> 0 then failwith "sfdisk --part-attrs failed";
|
||
|
+ udev_settle ()
|
||
|
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
|
||
|
index 68627078f..46ef1422f 100644
|
||
|
--- a/generator/actions_core.ml
|
||
|
+++ b/generator/actions_core.ml
|
||
|
@@ -5302,7 +5302,7 @@ See also C<guestfs_part_set_bootable>." };
|
||
|
{ defaults with
|
||
|
name = "part_get_mbr_id"; added = (1, 3, 2);
|
||
|
style = RInt "idbyte", [String (Device, "device"); Int "partnum"], [];
|
||
|
- impl = OCaml "Parted.part_get_mbr_id";
|
||
|
+ impl = OCaml "Sfdisk.part_get_mbr_id";
|
||
|
fish_output = Some FishOutputHexadecimal;
|
||
|
tests = [
|
||
|
InitEmpty, Always, TestResult (
|
||
|
@@ -8128,7 +8128,7 @@ group with GUID C<diskgroup>." };
|
||
|
{ defaults with
|
||
|
name = "part_set_gpt_type"; added = (1, 21, 1);
|
||
|
style = RErr, [String (Device, "device"); Int "partnum"; String (GUID, "guid")], [];
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_set_gpt_type";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestLastFail (
|
||
|
[["part_set_gpt_type"; "/dev/sda"; "1"; "f"]]), [];
|
||
|
@@ -8150,8 +8150,7 @@ for a useful list of type GUIDs." };
|
||
|
{ defaults with
|
||
|
name = "part_get_gpt_type"; added = (1, 21, 1);
|
||
|
style = RString (RPlainString, "guid"), [String (Device, "device"); Int "partnum"], [];
|
||
|
- impl = OCaml "Parted.part_get_gpt_type";
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_get_gpt_type";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestResultString (
|
||
|
[["part_set_gpt_type"; "/dev/sda"; "1";
|
||
|
@@ -8166,8 +8165,7 @@ Return the type GUID of numbered GPT partition C<partnum>." };
|
||
|
{ defaults with
|
||
|
name = "part_set_gpt_attributes"; added = (1, 21, 1);
|
||
|
style = RErr, [String (Device, "device"); Int "partnum"; Int64 "attributes"], [];
|
||
|
- impl = OCaml "Parted.part_set_gpt_attributes";
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_set_gpt_attributes";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestResult (
|
||
|
[["part_set_gpt_attributes"; "/dev/sda"; "1";
|
||
|
@@ -8186,8 +8184,7 @@ for a useful list of partition attributes." };
|
||
|
{ defaults with
|
||
|
name = "part_get_gpt_attributes"; added = (1, 21, 1);
|
||
|
style = RInt64 "attributes", [String (Device, "device"); Int "partnum"], [];
|
||
|
- impl = OCaml "Parted.part_get_gpt_attributes";
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_get_gpt_attributes";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestResult (
|
||
|
[["part_set_gpt_attributes"; "/dev/sda"; "1";
|
||
|
@@ -8987,7 +8984,7 @@ Recover bad superblocks from good copies." };
|
||
|
{ defaults with
|
||
|
name = "part_set_gpt_guid"; added = (1, 29, 25);
|
||
|
style = RErr, [String (Device, "device"); Int "partnum"; String (GUID, "guid")], [];
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_set_gpt_guid";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestLastFail (
|
||
|
[["part_set_gpt_guid"; "/dev/sda"; "1"; "f"]]), [];
|
||
|
@@ -9006,8 +9003,7 @@ valid GUID." };
|
||
|
{ defaults with
|
||
|
name = "part_get_gpt_guid"; added = (1, 29, 25);
|
||
|
style = RString (RPlainString, "guid"), [String (Device, "device"); Int "partnum"], [];
|
||
|
- impl = OCaml "Parted.part_get_gpt_guid";
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_get_gpt_guid";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestResultString (
|
||
|
[["part_set_gpt_guid"; "/dev/sda"; "1";
|
||
|
@@ -9206,7 +9202,7 @@ This is the internal call which implements C<guestfs_feature_available>." };
|
||
|
{ defaults with
|
||
|
name = "part_set_disk_guid"; added = (1, 33, 2);
|
||
|
style = RErr, [String (Device, "device"); String (GUID, "guid")], [];
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_set_disk_guid";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestLastFail (
|
||
|
[["part_set_disk_guid"; "/dev/sda"; "f"]]), [];
|
||
|
@@ -9225,7 +9221,7 @@ or if C<guid> is not a valid GUID." };
|
||
|
{ defaults with
|
||
|
name = "part_get_disk_guid"; added = (1, 33, 2);
|
||
|
style = RString (RPlainString, "guid"), [String (Device, "device")], [];
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_get_disk_guid";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestResultString (
|
||
|
[["part_set_disk_guid"; "/dev/sda";
|
||
|
@@ -9241,7 +9237,7 @@ Behaviour is undefined for other partition types." };
|
||
|
{ defaults with
|
||
|
name = "part_set_disk_guid_random"; added = (1, 33, 2);
|
||
|
style = RErr, [String (Device, "device")], [];
|
||
|
- optional = Some "gdisk";
|
||
|
+ impl = OCaml "Sfdisk.part_set_disk_guid_random";
|
||
|
tests = [
|
||
|
InitGPT, Always, TestRun (
|
||
|
[["part_set_disk_guid_random"; "/dev/sda"]]), [];
|
||
|
--
|
||
|
2.43.0
|
||
|
|