Enable building for ppc64le

This commit is contained in:
Eduard Abdullin 2025-05-14 02:07:17 +00:00 committed by root
commit edae3a5434
24 changed files with 1669 additions and 3389 deletions

View File

@ -1,79 +0,0 @@
From 1b27b7ed1a24030fc840123badf514e0a7b58341 Mon Sep 17 00:00:00 2001
From: Ricky Tigg <ricky.tigg@gmail.com>
Date: Fri, 4 Apr 2025 10:06:26 +0000
Subject: [PATCH] Translated using Weblate (Finnish)
Currently translated at 9.7% (94 of 960 strings)
Translation: libguestfs/libguestfs-master
Translate-URL: https://translate.fedoraproject.org/projects/libguestfs/libguestfs-master/fi/
---
po/fi.po | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/po/fi.po b/po/fi.po
index 27e511b4a..5c01bd861 100644
--- a/po/fi.po
+++ b/po/fi.po
@@ -6,10 +6,10 @@
msgid ""
msgstr ""
"Project-Id-Version: libguestfs 1.43.2\n"
-"Report-Msgid-Bugs-To: https://bugzilla.redhat.com/enter_bug.cgi?"
-"component=libguestfs&product=Virtualization+Tools\n"
+"Report-Msgid-Bugs-To: https://bugzilla.redhat.com/"
+"enter_bug.cgi?component=libguestfs&product=Virtualization+Tools\n"
"POT-Creation-Date: 2025-03-11 14:34+0000\n"
-"PO-Revision-Date: 2025-01-11 07:16+0000\n"
+"PO-Revision-Date: 2025-04-04 10:05+0000\n"
"Last-Translator: Ricky Tigg <ricky.tigg@gmail.com>\n"
"Language-Team: Finnish <https://translate.fedoraproject.org/projects/"
"libguestfs/libguestfs-master/fi/>\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 5.9.2\n"
+"X-Generator: Weblate 5.10.4\n"
#: common/options/config.c:72
#, c-format
@@ -453,7 +453,7 @@ msgstr ""
#: fish/cmds.c:540
msgid "upload base64-encoded data to file"
-msgstr ""
+msgstr "lataa ulospäin base64-koodatut tiedot tiedostoon"
#: fish/cmds.c:541
msgid "download file and encode as base64"
@@ -810,7 +810,7 @@ msgstr ""
#: fish/cmds.c:637
msgid "upload a file to the appliance (internal use only)"
-msgstr ""
+msgstr "lataa ulospäin tiedosto laitteeseen (vain sisäiseen käyttöön)"
#: fish/cmds.c:638
msgid "delete a previously registered event handler"
@@ -2440,7 +2440,7 @@ msgstr ""
#: fish/cmds.c:1150
msgid "upload a file from the local machine"
-msgstr ""
+msgstr "lataa ulospäin tiedosto paikalliselta koneelta"
#: fish/cmds.c:1151
msgid "upload a file from the local machine with offset"
@@ -2448,7 +2448,7 @@ msgstr ""
#: fish/cmds.c:1152
msgid "cancel the current upload or download operation"
-msgstr ""
+msgstr "peruuta nykyinen ulospäin-lataus- tai lataustoiminto"
#: fish/cmds.c:1153
msgid "set timestamp of a file with nanosecond precision"
--
2.47.1

View File

@ -0,0 +1,38 @@
From f6b1a7b57f96f002074e626d58b58f4244080ec9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 9 May 2025 15:52:30 +0100
Subject: [PATCH] appliance: Remove zfs-fuse
zfs-fuse has been unmaintained for a very long time. In fact, the
website has gone. This means that whatever we need for zfs (probably
some kind of license-compatible kernel module) is not going to be
provided by zfs-fuse.
See: https://bugzilla.redhat.com/show_bug.cgi?id=2214965
---
appliance/packagelist.in | 2 --
1 file changed, 2 deletions(-)
diff --git a/appliance/packagelist.in b/appliance/packagelist.in
index d0637631d..f8c80af24 100644
--- a/appliance/packagelist.in
+++ b/appliance/packagelist.in
@@ -51,7 +51,6 @@ ifelse(REDHAT,1,
systemd dnl for /sbin/reboot and udevd
vim-minimal
xz
- zfs-fuse
zstd
)
@@ -95,7 +94,6 @@ dnl isc-dhcp-client has been replaced with dhcpcd-base
ufsutils
vim-tiny
xz-utils
- zfs-fuse
zstd
uuid-runtime
)
--
2.47.1

View File

@ -0,0 +1,706 @@
From fcd169476f403f9f4f65dddd7c4f05a76b35baeb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 10 May 2025 18:29:40 +0100
Subject: [PATCH] Update common submodule
Adds these commits:
Richard W.M. Jones (5):
mlstdutils: Modify List.take, List.drop to match OCaml 5.3
mlstdutils: Rename List.dropwhile -> drop_while, takewhile -> take_while
mlstdutils: Add List.last function
mlstdutils: Move List module first
mlstdutils: Add String.common_prefix, longest_common_prefix
---
common | 2 +-
contrib/visualize-alignment/tracetops.ml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
Submodule common aa797fa13..4c7ae1581:
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 8462752..159fc4a 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -18,6 +18,138 @@
open Printf
+module List = struct
+ include List
+
+ (* Drop elements from a list while a predicate is true. *)
+ let rec drop_while f = function
+ | [] -> []
+ | x :: xs when f x -> drop_while f xs
+ | xs -> xs
+
+ (* Take elements from a list while a predicate is true. *)
+ let rec take_while f = function
+ | x :: xs when f x -> x :: take_while f xs
+ | _ -> []
+
+ let take n xs =
+ if n < 0 then invalid_arg "List.take"
+ else if n = 0 then []
+ else (
+ (* This optimisation avoids copying xs. *)
+ let len = List.length xs in
+ if len <= n then xs
+ else (
+ let rec take n = function
+ | x :: xs when n >= 1 -> x :: take (n-1) xs
+ | _ -> []
+ in
+ take n xs
+ )
+ )
+ let rec drop n xs =
+ if n < 0 then invalid_arg "List.drop"
+ else if n = 0 then xs
+ else if xs = [] then []
+ else drop (n-1) (List.tl xs)
+
+ let rec last = function
+ | [] -> invalid_arg "List.last"
+ | [x] -> x
+ | _ :: xs -> last xs
+
+ let rec filter_map f = function
+ | [] -> []
+ | x :: xs ->
+ match f x with
+ | Some y -> y :: filter_map f xs
+ | None -> filter_map f xs
+
+ let rec find_map f = function
+ | [] -> raise Not_found
+ | x :: xs ->
+ match f x with
+ | Some y -> y
+ | None -> find_map f xs
+
+ let rec group_by = function
+ | [] -> []
+ | (day1, x1) :: (day2, x2) :: rest when day1 = day2 ->
+ let rest = group_by ((day2, x2) :: rest) in
+ let day, xs = List.hd rest in
+ (day, x1 :: xs) :: List.tl rest
+ | (day, x) :: rest ->
+ (day, [x]) :: group_by rest
+
+ let rec combine3 xs ys zs =
+ match xs, ys, zs with
+ | [], [], [] -> []
+ | x::xs, y::ys, z::zs -> (x, y, z) :: combine3 xs ys zs
+ | _ -> invalid_arg "combine3"
+
+ let rec assoc_lbl ?(cmp = Stdlib.compare) ~default x = function
+ | [] -> default
+ | (y, y') :: _ when cmp x y = 0 -> y'
+ | _ :: ys -> assoc_lbl ~cmp ~default x ys
+
+ let uniq ?(cmp = Stdlib.compare) xs =
+ let rec loop acc = function
+ | [] -> acc
+ | [x] -> x :: acc
+ | x :: (y :: _ as xs) when cmp x y = 0 ->
+ loop acc xs
+ | x :: (y :: _ as xs) ->
+ loop (x :: acc) xs
+ in
+ List.rev (loop [] xs)
+
+ let remove_duplicates xs =
+ let h = Hashtbl.create (List.length xs) in
+ let rec loop = function
+ | [] -> []
+ | x :: xs when Hashtbl.mem h x -> xs
+ | x :: xs -> Hashtbl.add h x true; x :: loop xs
+ in
+ loop xs
+
+ let push_back xsp x = xsp := !xsp @ [x]
+ let push_front x xsp = xsp := x :: !xsp
+ let pop_back xsp =
+ let x, xs =
+ match List.rev !xsp with
+ | x :: xs -> x, xs
+ | [] -> failwith "pop" in
+ xsp := List.rev xs;
+ x
+ let pop_front xsp =
+ let x, xs =
+ match !xsp with
+ | x :: xs -> x, xs
+ | [] -> failwith "shift" in
+ xsp := xs;
+ x
+
+ let may_push_back xsp x =
+ match x with None -> () | Some x -> push_back xsp x
+ let may_push_front x xsp =
+ match x with None -> () | Some x -> push_front x xsp
+
+ let push_back_list xsp xs = xsp := !xsp @ xs
+ let push_front_list xs xsp = xsp := xs @ !xsp
+
+ let make n x =
+ let rec loop acc = function
+ | 0 -> acc
+ | i when i > 0 -> loop (x :: acc) (i-1)
+ | _ -> invalid_arg "make"
+ in
+ loop [] n
+
+ let same = function
+ | [] -> true
+ | x :: xs -> List.for_all ((=) x) xs
+end
+
module Char = struct
include Char
@@ -302,131 +434,23 @@ module String = struct
loop 0
let unix2dos str = replace str "\n" "\r\n"
-end
-module List = struct
- include List
-
- (* Drop elements from a list while a predicate is true. *)
- let rec dropwhile f = function
- | [] -> []
- | x :: xs when f x -> dropwhile f xs
- | xs -> xs
-
- (* Take elements from a list while a predicate is true. *)
- let rec takewhile f = function
- | x :: xs when f x -> x :: takewhile f xs
- | _ -> []
-
- let take n xs =
- if n <= 0 then []
- else (
- (* This optimisation avoids copying xs. *)
- let len = List.length xs in
- if len <= n then xs
- else (
- let rec take n = function
- | x :: xs when n >= 1 -> x :: take (n-1) xs
- | _ -> []
- in
- take n xs
- )
- )
- let rec drop n xs =
- if n <= 0 then xs
- else if xs = [] then []
- else drop (n-1) (List.tl xs)
-
- let rec filter_map f = function
- | [] -> []
- | x :: xs ->
- match f x with
- | Some y -> y :: filter_map f xs
- | None -> filter_map f xs
-
- let rec find_map f = function
- | [] -> raise Not_found
- | x :: xs ->
- match f x with
- | Some y -> y
- | None -> find_map f xs
-
- let rec group_by = function
- | [] -> []
- | (day1, x1) :: (day2, x2) :: rest when day1 = day2 ->
- let rest = group_by ((day2, x2) :: rest) in
- let day, xs = List.hd rest in
- (day, x1 :: xs) :: List.tl rest
- | (day, x) :: rest ->
- (day, [x]) :: group_by rest
-
- let rec combine3 xs ys zs =
- match xs, ys, zs with
- | [], [], [] -> []
- | x::xs, y::ys, z::zs -> (x, y, z) :: combine3 xs ys zs
- | _ -> invalid_arg "combine3"
-
- let rec assoc_lbl ?(cmp = Stdlib.compare) ~default x = function
- | [] -> default
- | (y, y') :: _ when cmp x y = 0 -> y'
- | _ :: ys -> assoc_lbl ~cmp ~default x ys
-
- let uniq ?(cmp = Stdlib.compare) xs =
- let rec loop acc = function
- | [] -> acc
- | [x] -> x :: acc
- | x :: (y :: _ as xs) when cmp x y = 0 ->
- loop acc xs
- | x :: (y :: _ as xs) ->
- loop (x :: acc) xs
+ let rec longest_common_prefix = function
+ | [] -> ""
+ | [s] -> s
+ | strs ->
+ let strs = List.sort compare strs in
+ let s1 = List.hd strs and s2 = List.last strs in
+ common_prefix s1 s2
+ and common_prefix s1 s2 =
+ let n1 = length s1 and n2 = length s2 in
+ let n = min n1 n2 in
+ let rec loop i =
+ if i = n then sub s1 0 n
+ else if unsafe_get s1 i <> unsafe_get s2 i then sub s1 0 i
+ else loop (i+1)
in
- List.rev (loop [] xs)
-
- let remove_duplicates xs =
- let h = Hashtbl.create (List.length xs) in
- let rec loop = function
- | [] -> []
- | x :: xs when Hashtbl.mem h x -> xs
- | x :: xs -> Hashtbl.add h x true; x :: loop xs
- in
- loop xs
-
- let push_back xsp x = xsp := !xsp @ [x]
- let push_front x xsp = xsp := x :: !xsp
- let pop_back xsp =
- let x, xs =
- match List.rev !xsp with
- | x :: xs -> x, xs
- | [] -> failwith "pop" in
- xsp := List.rev xs;
- x
- let pop_front xsp =
- let x, xs =
- match !xsp with
- | x :: xs -> x, xs
- | [] -> failwith "shift" in
- xsp := xs;
- x
-
- let may_push_back xsp x =
- match x with None -> () | Some x -> push_back xsp x
- let may_push_front x xsp =
- match x with None -> () | Some x -> push_front x xsp
-
- let push_back_list xsp xs = xsp := !xsp @ xs
- let push_front_list xs xsp = xsp := xs @ !xsp
-
- let make n x =
- let rec loop acc = function
- | 0 -> acc
- | i when i > 0 -> loop (x :: acc) (i-1)
- | _ -> invalid_arg "make"
- in
- loop [] n
-
- let same = function
- | [] -> true
- | x :: xs -> List.for_all ((=) x) xs
+ loop 0
end
let (//) = Filename.concat
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index 566c5b5..2526100 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -16,138 +16,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
-module Char : sig
- type t = char
- val chr : int -> char
- val code : char -> int
- val compare: t -> t -> int
- val escaped : char -> string
- val unsafe_chr : int -> char
-
- val lowercase_ascii : char -> char
- val uppercase_ascii : char -> char
-
- val isspace : char -> bool
- (** Return true if char is a whitespace character. *)
- val isdigit : char -> bool
- (** Return true if the character is a digit [[0-9]]. *)
- val isxdigit : char -> bool
- (** Return true if the character is a hex digit [[0-9a-fA-F]]. *)
- val isalpha : char -> bool
- (** Return true if the character is a US ASCII 7 bit alphabetic. *)
- val isalnum : char -> bool
- (** Return true if the character is a US ASCII 7 bit alphanumeric. *)
-
- val hexdigit : char -> int
- (** Return the value of a hex digit. If the char is not in
- the set [[0-9a-fA-F]] then this returns [-1]. *)
-
- val mem : char -> string -> bool
- (** [mem c str] returns true if the byte [c] is contained in [str].
-
- This is actually the same as {!String.contains} with the
- parameters reversed. *)
-end
-(** Override the Char module from stdlib. *)
-
-module String : sig
- type t = string
- val compare: t -> t -> int
- val concat : string -> string list -> string
- val contains : string -> char -> bool
- val contains_from : string -> int -> char -> bool
- val escaped : string -> string
- val get : string -> int -> char
- val index : string -> char -> int
- val index_from : string -> int -> char -> int
- val iter : (char -> unit) -> string -> unit
- val iteri : (int -> char -> unit) -> string -> unit
- val map : (char -> char) -> string -> string
- val length : string -> int
- val make : int -> char -> string
- val rcontains_from : string -> int -> char -> bool
- val rindex : string -> char -> int
- val rindex_from : string -> int -> char -> int
- val sub : string -> int -> int -> string
- val unsafe_get : string -> int -> char
-
- val lowercase_ascii : string -> string
- val uppercase_ascii : string -> string
- val capitalize_ascii : string -> string
-
- val is_prefix : string -> string -> bool
- (** [is_prefix str prefix] returns true if [prefix] is a prefix of [str]. *)
- val is_suffix : string -> string -> bool
- (** [is_suffix str suffix] returns true if [suffix] is a suffix of [str]. *)
- val find : string -> string -> int
- (** [find str sub] searches for [sub] as a substring of [str]. If
- found it returns the index. If not found, it returns [-1]. *)
- val find_from : string -> int -> string -> int
- (** [find_from str start sub] searches for [sub] as a substring of [str],
- starting at index [start]. If found it returns the index.
- If not found, it returns [-1]. *)
- val replace : string -> string -> string -> string
- (** [replace str s1 s2] replaces all instances of [s1] appearing in
- [str] with [s2]. *)
- val replace_char : string -> char -> char -> string
- (** Replace character in string. *)
- val break : int -> string -> string * string
- (** [break n str] breaks a string at the nth byte, returning the
- first and second parts. If [n] is beyond the end of the
- string it returns [(str, "")]. *)
- val split : string -> string -> string * string
- (** [split sep str] splits [str] at the first occurrence of the
- separator [sep], returning the part before and the part after.
- If separator is not found, return the whole string and an
- empty string. *)
- val nsplit : ?max:int -> string -> string -> string list
- (** [nsplit ?max sep str] splits [str] into multiple strings at each
- separator [sep].
-
- As with the Perl split function, you can give an optional
- [?max] parameter to limit the number of strings returned. The
- final element of the list will contain the remainder of the
- input string. *)
- val lines_split : string -> string list
- (** [lines_split str] splits [str] into lines, keeping continuation
- characters (i.e. [\] at the end of lines) into account. *)
- val random8 : unit -> string
- (** Return a string of 8 random printable characters. *)
- val triml : ?test:(char -> bool) -> string -> string
- (** Trim left. *)
- val trimr : ?test:(char -> bool) -> string -> string
- (** Trim right. *)
- val trim : ?test:(char -> bool) -> string -> string
- (** Trim left and right. *)
- val chomp : string -> string
- (** If the string ends with [\n], remove it. *)
- val count_chars : char -> string -> int
- (** Count number of times the character occurs in string. *)
- val explode : string -> char list
- (** Explode a string into a list of characters. *)
- val map_chars : (char -> 'a) -> string -> 'a list
- (** Explode string, then map function over the characters. *)
- val implode : char list -> string
- (** Join list of characters into a single string. *)
- val spaces : int -> string
- (** [spaces n] creates a string of n spaces. *)
- val span : string -> string -> int
- val cspan : string -> string -> int
- (** [span str accept] returns the length in bytes of the initial
- segment of [str] which contains only bytes in [accept].
-
- [cspan str reject] returns the length in bytes of the initial
- segment of [str] which contains only bytes {!i not} in [reject].
-
- These work exactly like the C functions [strspn] and [strcspn]. *)
- val unix2dos : string -> string
- (** Convert string with ordinary Unix-style line-endings to
- CRLF DOS-style line-endings.
-
- The same as {!String.replace} [str "\n" "\r\n"]. *)
-end
-(** Override the String module from stdlib. *)
-
module List : sig
val length : 'a list -> int
val hd : 'a list -> 'a
@@ -194,11 +62,11 @@ module List : sig
val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
- val dropwhile : ('a -> bool) -> 'a list -> 'a list
- (** [dropwhile f xs] drops leading elements from [xs] until
+ val drop_while : ('a -> bool) -> 'a list -> 'a list
+ (** [drop_while f xs] drops leading elements from [xs] until
[f] returns false. *)
- val takewhile : ('a -> bool) -> 'a list -> 'a list
- (** [takewhile f xs] takes leading elements from [xs] until
+ val take_while : ('a -> bool) -> 'a list -> 'a list
+ (** [take_while f xs] takes leading elements from [xs] until
[f] returns false.
For any list [xs] and function [f],
@@ -206,12 +74,21 @@ module List : sig
val take : int -> 'a list -> 'a list
(** [take n xs] returns the first [n] elements of [xs]. If [xs] is
- shorter than [n], then it returns [xs]. Note it never fails
- for any input. *)
+ shorter than [n], then it returns [xs]. [n] must be non-negative.
+
+ @raise Invalid_argument if [n] is negative *)
val drop : int -> 'a list -> 'a list
(** [drop n xs] returns the suffix of [xs] after the first [n]
elements. If [xs] is shorter than [n], then it returns the empty
- list. Note it never fails for any input. *)
+ list. [n] must be non-negative.
+
+ @raise Invalid_argument if [n] is negative *)
+
+ val last : 'a list -> 'a
+ (** Return the last element in the list (analogous to {!List.hd} but
+ much less efficient).
+
+ @raise Invalid_argument if the list is empty *)
val filter_map : ('a -> 'b option) -> 'a list -> 'b list
(** [filter_map f xs] applies [f] to each element of [xs]. If
@@ -302,6 +179,144 @@ module List : sig
end
(** Override the List module from stdlib. *)
+module Char : sig
+ type t = char
+ val chr : int -> char
+ val code : char -> int
+ val compare: t -> t -> int
+ val escaped : char -> string
+ val unsafe_chr : int -> char
+
+ val lowercase_ascii : char -> char
+ val uppercase_ascii : char -> char
+
+ val isspace : char -> bool
+ (** Return true if char is a whitespace character. *)
+ val isdigit : char -> bool
+ (** Return true if the character is a digit [[0-9]]. *)
+ val isxdigit : char -> bool
+ (** Return true if the character is a hex digit [[0-9a-fA-F]]. *)
+ val isalpha : char -> bool
+ (** Return true if the character is a US ASCII 7 bit alphabetic. *)
+ val isalnum : char -> bool
+ (** Return true if the character is a US ASCII 7 bit alphanumeric. *)
+
+ val hexdigit : char -> int
+ (** Return the value of a hex digit. If the char is not in
+ the set [[0-9a-fA-F]] then this returns [-1]. *)
+
+ val mem : char -> string -> bool
+ (** [mem c str] returns true if the byte [c] is contained in [str].
+
+ This is actually the same as {!String.contains} with the
+ parameters reversed. *)
+end
+(** Override the Char module from stdlib. *)
+
+module String : sig
+ type t = string
+ val compare: t -> t -> int
+ val concat : string -> string list -> string
+ val contains : string -> char -> bool
+ val contains_from : string -> int -> char -> bool
+ val escaped : string -> string
+ val get : string -> int -> char
+ val index : string -> char -> int
+ val index_from : string -> int -> char -> int
+ val iter : (char -> unit) -> string -> unit
+ val iteri : (int -> char -> unit) -> string -> unit
+ val map : (char -> char) -> string -> string
+ val length : string -> int
+ val make : int -> char -> string
+ val rcontains_from : string -> int -> char -> bool
+ val rindex : string -> char -> int
+ val rindex_from : string -> int -> char -> int
+ val sub : string -> int -> int -> string
+ val unsafe_get : string -> int -> char
+
+ val lowercase_ascii : string -> string
+ val uppercase_ascii : string -> string
+ val capitalize_ascii : string -> string
+
+ val is_prefix : string -> string -> bool
+ (** [is_prefix str prefix] returns true if [prefix] is a prefix of [str]. *)
+ val is_suffix : string -> string -> bool
+ (** [is_suffix str suffix] returns true if [suffix] is a suffix of [str]. *)
+ val find : string -> string -> int
+ (** [find str sub] searches for [sub] as a substring of [str]. If
+ found it returns the index. If not found, it returns [-1]. *)
+ val find_from : string -> int -> string -> int
+ (** [find_from str start sub] searches for [sub] as a substring of [str],
+ starting at index [start]. If found it returns the index.
+ If not found, it returns [-1]. *)
+ val replace : string -> string -> string -> string
+ (** [replace str s1 s2] replaces all instances of [s1] appearing in
+ [str] with [s2]. *)
+ val replace_char : string -> char -> char -> string
+ (** Replace character in string. *)
+ val break : int -> string -> string * string
+ (** [break n str] breaks a string at the nth byte, returning the
+ first and second parts. If [n] is beyond the end of the
+ string it returns [(str, "")]. *)
+ val split : string -> string -> string * string
+ (** [split sep str] splits [str] at the first occurrence of the
+ separator [sep], returning the part before and the part after.
+ If separator is not found, return the whole string and an
+ empty string. *)
+ val nsplit : ?max:int -> string -> string -> string list
+ (** [nsplit ?max sep str] splits [str] into multiple strings at each
+ separator [sep].
+
+ As with the Perl split function, you can give an optional
+ [?max] parameter to limit the number of strings returned. The
+ final element of the list will contain the remainder of the
+ input string. *)
+ val lines_split : string -> string list
+ (** [lines_split str] splits [str] into lines, keeping continuation
+ characters (i.e. [\] at the end of lines) into account. *)
+ val random8 : unit -> string
+ (** Return a string of 8 random printable characters. *)
+ val triml : ?test:(char -> bool) -> string -> string
+ (** Trim left. *)
+ val trimr : ?test:(char -> bool) -> string -> string
+ (** Trim right. *)
+ val trim : ?test:(char -> bool) -> string -> string
+ (** Trim left and right. *)
+ val chomp : string -> string
+ (** If the string ends with [\n], remove it. *)
+ val count_chars : char -> string -> int
+ (** Count number of times the character occurs in string. *)
+ val explode : string -> char list
+ (** Explode a string into a list of characters. *)
+ val map_chars : (char -> 'a) -> string -> 'a list
+ (** Explode string, then map function over the characters. *)
+ val implode : char list -> string
+ (** Join list of characters into a single string. *)
+ val spaces : int -> string
+ (** [spaces n] creates a string of n spaces. *)
+ val span : string -> string -> int
+ val cspan : string -> string -> int
+ (** [span str accept] returns the length in bytes of the initial
+ segment of [str] which contains only bytes in [accept].
+
+ [cspan str reject] returns the length in bytes of the initial
+ segment of [str] which contains only bytes {!i not} in [reject].
+
+ These work exactly like the C functions [strspn] and [strcspn]. *)
+ val unix2dos : string -> string
+ (** Convert string with ordinary Unix-style line-endings to
+ CRLF DOS-style line-endings.
+
+ The same as {!String.replace} [str "\n" "\r\n"]. *)
+ val common_prefix : string -> string -> string
+ (** Return the longest common prefix of two strings. *)
+ val longest_common_prefix : string list -> string
+ (** Return the longest common prefix of all the strings in the list.
+ If the list is empty or there is no common prefix, [""] is
+ returned. If there is only one string in the list, it is returned. *)
+end
+(** Override the String module from stdlib. *)
+
val ( // ) : string -> string -> string
(** Concatenate directory and filename. *)
diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml
index aadab17..abe842b 100644
--- a/common/mlstdutils/std_utils_tests.ml
+++ b/common/mlstdutils/std_utils_tests.ml
@@ -190,6 +190,37 @@ let () =
assert_equal_string "" (String.chomp "\n");
assert_equal_string "\n" (String.chomp "\n\n") (* only removes one *)
+(* Test Std_utils.String.common_prefix, longest_common_prefix. *)
+let () =
+ assert_equal_string "" (String.common_prefix "" "");
+ assert_equal_string "" (String.common_prefix "" "abc");
+ assert_equal_string "" (String.common_prefix "abc" "");
+ assert_equal_string "" (String.common_prefix "hello" "world");
+ assert_equal_string "abc" (String.common_prefix "abc" "abcde");
+ assert_equal_string "abc" (String.common_prefix "abcde" "abc");
+ assert_equal_string "abc" (String.common_prefix "abcde" "abcghi");
+ assert_equal_string "" (String.longest_common_prefix []);
+ assert_equal_string "" (String.longest_common_prefix [""]);
+ assert_equal_string "abc" (String.longest_common_prefix ["abc"]);
+ assert_equal_string "" (String.longest_common_prefix [""; "abc"]);
+ assert_equal_string "" (String.longest_common_prefix ["abc"; ""]);
+ assert_equal_string "" (String.longest_common_prefix ["hello"; "world"]);
+ assert_equal_string ""
+ (String.longest_common_prefix ["hello"; "there"; "world"]);
+ assert_equal_string "abc" (String.longest_common_prefix ["abc"; "abcde"]);
+ assert_equal_string "abc" (String.longest_common_prefix ["abcde"; "abc"]);
+ assert_equal_string "abc" (String.longest_common_prefix ["abcde"; "abcghi"]);
+ assert_equal_string "abc"
+ (String.longest_common_prefix ["abcde"; "abcghi"; "abc123"]);
+ assert_equal_string "abc"
+ (String.longest_common_prefix ["abc"; "abcghi"; "abc123"]);
+ assert_equal_string "abc"
+ (String.longest_common_prefix ["abcde"; "abc"; "abc123"]);
+ assert_equal_string "abc"
+ (String.longest_common_prefix ["abcde"; "abcde"; "abc"]);
+ assert_equal_string "abc"
+ (String.longest_common_prefix ["abc"; "abc"; "abc"])
+
(* Test Std_utils.which. *)
let () =
assert_nonempty_string (which "true");
@@ -216,3 +247,9 @@ let () =
let () =
assert_bool "List.same []" (List.same (List.make 0 "1"));
assert_bool "List.same [1; 1; ...; 1]" (List.same (List.make 10 1))
+
+(* Test List.last. *)
+let () =
+ assert_equal_string "3" (List.last ["1"; "2"; "3"]);
+ assert_equal_string "1" (List.last ["1"]);
+ assert_raises (Invalid_argument "List.last") (fun () -> List.last [])
diff --git a/contrib/visualize-alignment/tracetops.ml b/contrib/visualize-alignment/tracetops.ml
index b838b30f3..102a03580 100755
--- a/contrib/visualize-alignment/tracetops.ml
+++ b/contrib/visualize-alignment/tracetops.ml
@@ -185,7 +185,7 @@ let ranges =
loop i0 rest
| (false, i1) :: rest ->
let i1 = i1 - 1 in
- let rest = List.dropwhile (function (v, _) -> not v) rest in
+ let rest = List.drop_while (function (v, _) -> not v) rest in
(match rest with
| [] -> [i0, i1]
| (_, i2) :: rest -> (i0, i1) :: loop i2 rest)
--
2.47.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,248 @@
From c4ebeee5053a2f4ac87968121c29b64a596d42aa Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 11 May 2025 12:37:23 +0100
Subject: [PATCH] Update common submodule
Pull in these commits which require minor changes:
Richard W.M. Jones (3):
mlstdutils: Remove Std_utils.identity
mlstdutils: Remove Std_utils.protect
mlstdutils: Remove List.filter_map
---
common | 2 +-
daemon/btrfs.ml | 4 ++--
daemon/cryptsetup.ml | 2 +-
daemon/filearch.ml | 2 +-
daemon/inspect_utils.ml | 6 +++---
daemon/sfdisk.ml | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
Submodule common 4c7ae1581..3a05f1a7a:
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 159fc4a..39b5bc9 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -58,13 +58,6 @@ module List = struct
| [x] -> x
| _ :: xs -> last xs
- let rec filter_map f = function
- | [] -> []
- | x :: xs ->
- match f x with
- | Some y -> y :: filter_map f xs
- | None -> filter_map f xs
-
let rec find_map f = function
| [] -> raise Not_found
| x :: xs ->
@@ -463,8 +456,6 @@ let ( /^ ) = Int64.div
let ( &^ ) = Int64.logand
let ( ~^ ) = Int64.lognot
-external identity : 'a -> 'a = "%identity"
-
let roundup64 i a = let a = a -^ 1L in (i +^ a) &^ (~^ a)
let div_roundup64 i a = (i +^ a -^ 1L) /^ a
@@ -628,13 +619,6 @@ let unique = let i = ref 0 in fun () -> incr i; !i
type ('a, 'b) maybe = Either of 'a | Or of 'b
-let protect ~f ~finally =
- let r =
- try Either (f ())
- with exn -> Or exn in
- finally ();
- match r with Either ret -> ret | Or exn -> raise exn
-
type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
let with_return (type a) f =
let exception Return of a in
@@ -691,15 +675,15 @@ let wrap () = !wrap
let with_open_in filename f =
let chan = open_in filename in
- protect ~f:(fun () -> f chan) ~finally:(fun () -> close_in chan)
+ Fun.protect (fun () -> f chan) ~finally:(fun () -> close_in chan)
let with_open_out filename f =
let chan = open_out filename in
- protect ~f:(fun () -> f chan) ~finally:(fun () -> close_out chan)
+ Fun.protect (fun () -> f chan) ~finally:(fun () -> close_out chan)
let with_openfile filename flags perms f =
let fd = Unix.openfile filename flags perms in
- protect ~f:(fun () -> f fd) ~finally:(fun () -> Unix.close fd)
+ Fun.protect (fun () -> f fd) ~finally:(fun () -> Unix.close fd)
let read_whole_file path =
let buf = Buffer.create 16384 in
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index 2526100..04c780a 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -31,6 +31,7 @@ module List : sig
val map : ('a -> 'b) -> 'a list -> 'b list
val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
val rev_map : ('a -> 'b) -> 'a list -> 'b list
+ val filter_map : ('a -> 'b option) -> 'a list -> 'b list
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
val fold_right : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b
val iter2 : ('a -> 'b -> unit) -> 'a list -> 'b list -> unit
@@ -90,9 +91,6 @@ module List : sig
@raise Invalid_argument if the list is empty *)
- val filter_map : ('a -> 'b option) -> 'a list -> 'b list
- (** [filter_map f xs] applies [f] to each element of [xs]. If
- [f x] returns [Some y] then [y] is added to the returned list. *)
val find_map : ('a -> 'b option) -> 'a list -> 'b
(** [find_map f xs] applies [f] to each element of [xs] until
[f x] returns [Some y]. It returns [y]. If we exhaust the
@@ -331,8 +329,6 @@ val ( &^ ) : int64 -> int64 -> int64
val ( ~^ ) : int64 -> int64
(** Various int64 operators. *)
-external identity : 'a -> 'a = "%identity"
-
val roundup64 : int64 -> int64 -> int64
(** [roundup64 i a] returns [i] rounded up to the next multiple of [a]. *)
val div_roundup64 : int64 -> int64 -> int64
@@ -371,18 +367,6 @@ val unique : unit -> int
type ('a, 'b) maybe = Either of 'a | Or of 'b
(** Like the Haskell [Either] type. *)
-val protect : f:(unit -> 'a) -> finally:(unit -> unit) -> 'a
-(** Execute [~f] and afterwards execute [~finally].
-
- If [~f] throws an exception then [~finally] is run and the
- original exception from [~f] is re-raised.
-
- If [~finally] throws an exception, then the original exception
- is lost. (NB: Janestreet core {!Exn.protectx}, on which this
- function is modelled, doesn't throw away the exception in this
- case, but requires a lot more work by the caller. Perhaps we
- will change this in future.) *)
-
type 'a return = { return: 'b. 'a -> 'b } [@@unboxed]
val with_return : ('a return -> 'a) -> 'a
(** {v
diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml
index abe842b..10046bd 100644
--- a/common/mlstdutils/std_utils_tests.ml
+++ b/common/mlstdutils/std_utils_tests.ml
@@ -40,7 +40,7 @@ let assert_raises exn fn =
)
let assert_equal_string =
- assert_equal ~printer:identity
+ assert_equal ~printer:Fun.id
let assert_equal_int =
assert_equal ~printer:(fun x -> string_of_int x)
let assert_equal_int64 =
diff --git a/common/mlutils/c_utils_unit_tests.ml b/common/mlutils/c_utils_unit_tests.ml
index 961dac5..50c7e44 100644
--- a/common/mlutils/c_utils_unit_tests.ml
+++ b/common/mlutils/c_utils_unit_tests.ml
@@ -42,7 +42,7 @@ let assert_raises exn fn =
(* Test drive_name function. *)
let () =
- let printer = identity in
+ let printer = Fun.id in
assert_equal ~printer "a" (drive_name 0);
assert_equal ~printer "z" (drive_name 25);
assert_equal ~printer "aa" (drive_name 26);
@@ -74,7 +74,7 @@ let () =
(* Test shell_unquote function. *)
let () =
- let printer = identity in
+ let printer = Fun.id in
assert_equal ~printer "a" (shell_unquote "a");
assert_equal ~printer "b" (shell_unquote "'b'");
assert_equal ~printer "c" (shell_unquote "\"c\"");
diff --git a/daemon/btrfs.ml b/daemon/btrfs.ml
index 3f9d8308a..35e0b1765 100644
--- a/daemon/btrfs.ml
+++ b/daemon/btrfs.ml
@@ -48,7 +48,7 @@ let rec with_mounted mountable f =
rmdir tmpdir
in
- protect ~finally ~f:(fun () -> mount_cmd tmpdir; f tmpdir)
+ Fun.protect ~finally (fun () -> mount_cmd tmpdir; f tmpdir)
in
match mountable.m_type with
@@ -124,4 +124,4 @@ let btrfs_subvolume_get_default mountable =
with_mounted mountable (
fun mp -> command "btrfs" ["subvolume"; "get-default"; mp]
) in
- sscanf out "ID %Ld" identity
+ sscanf out "ID %Ld" Fun.id
diff --git a/daemon/cryptsetup.ml b/daemon/cryptsetup.ml
index ac2cf066e..9c0149b48 100644
--- a/daemon/cryptsetup.ml
+++ b/daemon/cryptsetup.ml
@@ -56,7 +56,7 @@ let cryptsetup_open ?(readonly = false) ?crypttype ?cipher device key mapname =
Option.iter (fun s -> List.push_back_list args ["--cipher"; s]) cipher;
(* Make sure we always remove the temporary file. *)
- protect ~f:(fun () -> ignore (command "cryptsetup" !args))
+ Fun.protect (fun () -> ignore (command "cryptsetup" !args))
~finally:(fun () -> unlink keyfile);
udev_settle ()
diff --git a/daemon/filearch.ml b/daemon/filearch.ml
index 6eed7d396..f45392b5f 100644
--- a/daemon/filearch.ml
+++ b/daemon/filearch.ml
@@ -116,7 +116,7 @@ and cpio_arch magic orig_path path =
let tmpdir = Mkdtemp.temp_dir "filearch" in
let finally () = ignore (Sys.command (sprintf "rm -rf %s" (quote tmpdir))) in
- protect ~finally ~f:(
+ Fun.protect ~finally (
fun () ->
(* Construct a command to extract named binaries from the initrd file. *)
let cmd =
diff --git a/daemon/inspect_utils.ml b/daemon/inspect_utils.ml
index 1aa762050..5ef8bfa25 100644
--- a/daemon/inspect_utils.ml
+++ b/daemon/inspect_utils.ml
@@ -57,8 +57,8 @@ let rec with_augeas ?name configfiles f =
Augeas.create (Sysroot.sysroot ()) None
[Augeas.AugSaveNoop; Augeas.AugNoLoad] in
- protect
- ~f:(fun () ->
+ Fun.protect
+ (fun () ->
(* Tell Augeas to only load configfiles and no other files. This
* prevents a rogue guest from performing a denial of service attack
* by having large, over-complicated configuration files which are
@@ -179,4 +179,4 @@ let with_hive hive_filename f =
| Some f -> f :: flags in
let flags = if verbose () then Hivex.OPEN_VERBOSE :: flags else flags in
let h = Hivex.open_file hive_filename flags in
- protect ~f:(fun () -> f h (Hivex.root h)) ~finally:(fun () -> Hivex.close h)
+ Fun.protect (fun () -> f h (Hivex.root h)) ~finally:(fun () -> Hivex.close h)
diff --git a/daemon/sfdisk.ml b/daemon/sfdisk.ml
index c694c328c..3265d1e83 100644
--- a/daemon/sfdisk.ml
+++ b/daemon/sfdisk.ml
@@ -35,7 +35,7 @@ let part_get_mbr_id device partnum =
udev_settle ();
(* It's printed in hex, possibly with a leading space. *)
- sscanf out " %x" identity
+ sscanf out " %x" Fun.id
let part_get_gpt_type device partnum =
if partnum <= 0 then
--
2.47.1

View File

@ -1,43 +0,0 @@
From abdec091c4e277515815c14fc3d02eec57e22dea Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 9 Apr 2025 16:09:05 -0400
Subject: [PATCH] common: update submodule
Cole Robinson (2):
mltools: decouple and simplify osinfo device support checks
mlcustomize: disable `--inject-virtio-win osinfo`
Richard W.M. Jones (3):
mltools: Fix de-oUnit-ized tests
mltools: Unreference various objects
Revert "mltools: Unreference various objects"
And update customize docs to match
Signed-off-by: Cole Robinson <crobinso@redhat.com>
---
common | 2 +-
generator/customize.ml | 6 ------
2 files changed, 1 insertion(+), 7 deletions(-)
Submodule common 64f6ee85f..347b13716:
diff --git a/generator/customize.ml b/generator/customize.ml
index dc36afe70..fd6ebf588 100644
--- a/generator/customize.ml
+++ b/generator/customize.ml
@@ -341,12 +341,6 @@ The path to the ISO image containing the virtio-win drivers
The directory containing the unpacked virtio-win drivers
(eg. F</usr/share/virtio-win>).
-=item B<\"osinfo\">
-
-The literal string C<\"osinfo\"> means to use the
-libosinfo database to locate the drivers. (See
-L<osinfo-query(1)>.
-
=back
Note that to do a full conversion of a Windows guest from a
--
2.47.1

View File

@ -1,71 +0,0 @@
From 2d1e8941301373d04a436333219358a72f9660f1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 10:01:33 +0100
Subject: [PATCH] daemon: inspect: Add some debugging of /usr merging
---
daemon/inspect.ml | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/daemon/inspect.ml b/daemon/inspect.ml
index e3b6d71a1..2c027b7c5 100644
--- a/daemon/inspect.ml
+++ b/daemon/inspect.ml
@@ -47,18 +47,21 @@ let rec inspect_os () =
* multiple filesystems. Gather all the inspected information in the
* inspect_fs struct of the root filesystem.
*)
+ eprintf "inspect_os: collect_coreos_inspection_info\n%!";
let fses = collect_coreos_inspection_info fses in
(* Check if the same filesystem was listed twice as root in fses.
* This may happen for the *BSD root partition where an MBR partition
* is a shadow of the real root partition probably /dev/sda5
*)
+ eprintf "inspect_os: check_for_duplicated_bsd_root\n%!";
let fses = check_for_duplicated_bsd_root fses in
(* For Linux guests with a separate /usr filesystem, merge some of the
* inspected information in that partition to the inspect_fs struct
* of the root filesystem.
*)
+ eprintf "inspect_os: collect_linux_inspection_info\n%!";
let fses = collect_linux_inspection_info fses in
(* Save what we found in a global variable. *)
@@ -194,6 +197,9 @@ and collect_linux_inspection_info fses =
* or other ways to identify the OS).
*)
and collect_linux_inspection_info_for fses root =
+ eprintf "inspect_os: collect_linux_inspection_info_for %s\n"
+ (string_of_location root.fs_location);
+
let root_fstab =
match root with
| { role = RoleRoot { fstab = f } } -> f
@@ -207,14 +213,21 @@ and collect_linux_inspection_info_for fses root =
(* This checks that this usr is found in the fstab of
* the root filesystem.
*)
+ eprintf "inspect_os: checking if %s found in fstab of this root\n"
+ (string_of_location usr_mp);
List.exists (
fun (mountable, _) ->
+ eprintf "inspect_os: collect_linux_inspection_info_for: \
+ compare %s = %s\n"
+ (Mountable.to_string usr_mp.mountable)
+ (Mountable.to_string mountable);
usr_mp.mountable = mountable
) root_fstab
| _ -> false
) fses in
- eprintf "collect_linux_inspection_info_for: merging:\n%sinto:\n%s"
+ eprintf "inspect_os: collect_linux_inspection_info_for: merging:\n\
+ %sinto:\n%s"
(string_of_fs usr) (string_of_fs root);
merge usr root;
root
--
2.47.1

View File

@ -0,0 +1,25 @@
From 464b8915e9e9b871d64446b5dfc8a806f3d87883 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 11 May 2025 15:01:06 +0100
Subject: [PATCH] ocaml-dep.sh.in: Remove mlgettext subdirectory
Libguestfs does not use ocaml-gettext at all.
---
ocaml-dep.sh.in | 1 -
1 file changed, 1 deletion(-)
diff --git a/ocaml-dep.sh.in b/ocaml-dep.sh.in
index a9c093bb0..8cdfd76ba 100755
--- a/ocaml-dep.sh.in
+++ b/ocaml-dep.sh.in
@@ -33,7 +33,6 @@ set -e
# directories must have unique names (eg. not Utils) else
# dependencies don't get built right.
include_dirs="
-common/mlgettext
common/mlpcre
common/mlstdutils
common/mlutils
--
2.47.1

View File

@ -0,0 +1,531 @@
From f9edfc9a18eec134a38872166bb2e3dac51a8d18 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sun, 11 May 2025 21:21:56 +0100
Subject: [PATCH] Update common submodule
This pulls in the commits below, requiring us to replace all uses of
String.is_prefix and String.is_suffix.
Mostly done with Perl like this, and carefully checked by hand
afterwards since this doesn't get everything right:
$ perl -pi.bak -e 's/String.is_prefix ([^[:space:]\)]+) ([^[:space:]\)]+)/String.starts_with \2 \1/g' -- `git ls-files`
Richard W.M. Jones (3):
mlstdutils: Fix comment that still referred to the old function names
mldrivers: Link to gettext-stub if ocaml-gettext is enabled
mlstdutils: Rename String.is_prefix -> starts_with, is_suffix -> ends_with
---
common | 2 +-
daemon/cryptsetup.ml | 2 +-
daemon/devsparts.ml | 18 +++++++++---------
daemon/findfs.ml | 4 ++--
daemon/inspect_fs_unix.ml | 10 +++++-----
daemon/inspect_fs_unix_fstab.ml | 30 +++++++++++++++---------------
daemon/inspect_fs_windows.ml | 8 ++++----
daemon/ldm.ml | 2 +-
daemon/listfs.ml | 8 ++++----
daemon/md.ml | 2 +-
daemon/mount_utils.ml | 4 ++--
daemon/sfdisk.ml | 8 ++++----
daemon/utils.ml | 6 +++---
generator/daemon.ml | 2 +-
14 files changed, 53 insertions(+), 53 deletions(-)
Submodule common 3a05f1a7a..d4a81e9dd:
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 39b5bc9..4850a55 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -214,11 +214,11 @@ module String = struct
Bytes.unsafe_set b 0 (Char.uppercase_ascii (Bytes.unsafe_get b 0));
Bytes.to_string b
- let is_prefix str prefix =
+ let starts_with ~prefix str =
let n = length prefix in
length str >= n && sub str 0 n = prefix
- let is_suffix str suffix =
+ let ends_with ~suffix str =
let sufflen = length suffix
and len = length str in
len >= sufflen && sub str (len - sufflen) sufflen = suffix
@@ -824,7 +824,7 @@ let unix_like = function
| "hurd"
| "linux"
| "minix" -> true
- | typ when String.is_suffix typ "bsd" -> true
+ | typ when String.ends_with "bsd" typ -> true
| _ -> false
(** Return the last part of a string, after the specified separator. *)
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index 04c780a..fe6bf1a 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -71,7 +71,7 @@ module List : sig
[f] returns false.
For any list [xs] and function [f],
- [xs = takewhile f xs @ dropwhile f xs] *)
+ [xs = take_while f xs @ drop_while f xs] *)
val take : int -> 'a list -> 'a list
(** [take n xs] returns the first [n] elements of [xs]. If [xs] is
@@ -236,10 +236,10 @@ module String : sig
val uppercase_ascii : string -> string
val capitalize_ascii : string -> string
- val is_prefix : string -> string -> bool
- (** [is_prefix str prefix] returns true if [prefix] is a prefix of [str]. *)
- val is_suffix : string -> string -> bool
- (** [is_suffix str suffix] returns true if [suffix] is a suffix of [str]. *)
+ val starts_with : prefix:string -> string -> bool
+ (** Return true if [prefix] is a prefix of [str]. *)
+ val ends_with : suffix:string -> string -> bool
+ (** Return true if [suffix] is a suffix of [str]. *)
val find : string -> string -> int
(** [find str sub] searches for [sub] as a substring of [str]. If
found it returns the index. If not found, it returns [-1]. *)
diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml
index 10046bd..133c672 100644
--- a/common/mlstdutils/std_utils_tests.ml
+++ b/common/mlstdutils/std_utils_tests.ml
@@ -87,21 +87,23 @@ let () =
assert_bool "Char.mem" (not (Char.mem 'd' "abc"));
assert_bool "Char.mem" (not (Char.mem 'a' ""))
-(* Test Std_utils.String.is_prefix. *)
+(* Test Std_utils.String.starts_with. *)
let () =
- assert_bool "String.is_prefix,," (String.is_prefix "" "");
- assert_bool "String.is_prefix,foo," (String.is_prefix "foo" "");
- assert_bool "String.is_prefix,foo,foo" (String.is_prefix "foo" "foo");
- assert_bool "String.is_prefix,foo123,foo" (String.is_prefix "foo123" "foo");
- assert_bool "not (String.is_prefix,,foo" (not (String.is_prefix "" "foo"))
+ assert_bool "String.starts_with,," (String.starts_with "" "");
+ assert_bool "String.starts_with,foo," (String.starts_with "" "foo");
+ assert_bool "String.starts_with,foo,foo" (String.starts_with "foo" "foo");
+ assert_bool "String.starts_with,foo123,foo"
+ (String.starts_with "foo" "foo123");
+ assert_bool "not (String.starts_with,,foo"
+ (not (String.starts_with "foo" ""))
-(* Test Std_utils.String.is_suffix. *)
+(* Test Std_utils.String.ends_with. *)
let () =
- assert_bool "String.is_suffix,," (String.is_suffix "" "");
- assert_bool "String.is_suffix,foo," (String.is_suffix "foo" "");
- assert_bool "String.is_suffix,foo,foo" (String.is_suffix "foo" "foo");
- assert_bool "String.is_suffix,123foo,foo" (String.is_suffix "123foo" "foo");
- assert_bool "not String.is_suffix,,foo" (not (String.is_suffix "" "foo"))
+ assert_bool "String.ends_with,," (String.ends_with "" "");
+ assert_bool "String.ends_with,foo," (String.ends_with "" "foo");
+ assert_bool "String.ends_with,foo,foo" (String.ends_with "foo" "foo");
+ assert_bool "String.ends_with,123foo,foo" (String.ends_with "foo" "123foo");
+ assert_bool "not String.ends_with,,foo" (not (String.ends_with "foo" ""))
(* Test Std_utils.String.find. *)
let () =
diff --git a/daemon/cryptsetup.ml b/daemon/cryptsetup.ml
index 9c0149b48..6f677aef0 100644
--- a/daemon/cryptsetup.ml
+++ b/daemon/cryptsetup.ml
@@ -63,7 +63,7 @@ let cryptsetup_open ?(readonly = false) ?crypttype ?cipher device key mapname =
let cryptsetup_close device =
(* Must be /dev/mapper/... *)
- if not (String.is_prefix device "/dev/mapper/") then
+ if not (String.starts_with "/dev/mapper/" device) then
failwithf "%s: you must call this on the /dev/mapper device created by cryptsetup-open" device;
let mapname = String.sub device 12 (String.length device - 12) in
diff --git a/daemon/devsparts.ml b/daemon/devsparts.ml
index 639e163d4..6b45ebc8e 100644
--- a/daemon/devsparts.ml
+++ b/daemon/devsparts.ml
@@ -38,18 +38,18 @@ let map_block_devices f =
fun file ->
let dev = Unix_utils.Realpath.realpath (sprintf "%s/%s" path file) in
(* Ignore non-/dev devices, and return without /dev/ prefix. *)
- if String.is_prefix dev "/dev/" then
+ if String.starts_with "/dev/" dev then
Some (String.sub dev 5 (String.length dev - 5))
else
None
) devs in
let devs = List.filter (
fun dev ->
- String.is_prefix dev "sd" ||
- String.is_prefix dev "hd" ||
- String.is_prefix dev "ubd" ||
- String.is_prefix dev "vd" ||
- String.is_prefix dev "sr"
+ String.starts_with "sd" dev ||
+ String.starts_with "hd" dev ||
+ String.starts_with "ubd" dev ||
+ String.starts_with "vd" dev ||
+ String.starts_with "sr" dev
) devs in
(* Ignore the root device. *)
@@ -81,7 +81,7 @@ let map_md_devices f =
let devs = Array.to_list devs in
let devs = List.filter (
fun dev ->
- String.is_prefix dev "md" &&
+ String.starts_with "md" dev &&
String.length dev >= 3 && Char.isdigit dev.[2]
) devs in
List.map f devs
@@ -111,7 +111,7 @@ and add_partitions dev =
(* Look in /sys/block/<device>/ for entries starting with
* <device>, eg. /sys/block/sda/sda1.
*)
- let parts = List.filter (fun part -> String.is_prefix part dev) parts in
+ let parts = List.filter (fun part -> String.starts_with dev part) parts in
let parts = List.map ((^) "/dev/") parts in
sort_device_names parts
@@ -133,7 +133,7 @@ let is_whole_device device =
(* A 'whole' block device will have a symlink to the device in its
* /sys/block directory
*)
- assert (String.is_prefix device "/dev/");
+ assert (String.starts_with "/dev/" device);
let device = String.sub device 5 (String.length device - 5) in
let devpath = sprintf "/sys/block/%s/device" device in
diff --git a/daemon/findfs.ml b/daemon/findfs.ml
index d5752869c..087aad27f 100644
--- a/daemon/findfs.ml
+++ b/daemon/findfs.ml
@@ -46,8 +46,8 @@ and findfs tag str =
(* Trim trailing \n if present. *)
let out = String.trim out in
- if String.is_prefix out "/dev/mapper/" ||
- String.is_prefix out "/dev/dm-" then (
+ if String.starts_with "/dev/mapper/" out ||
+ String.starts_with "/dev/dm-" out then (
match Lvm_utils.lv_canonical out with
| None ->
(* Ignore the case where 'out' doesn't appear to be an LV.
diff --git a/daemon/inspect_fs_unix.ml b/daemon/inspect_fs_unix.ml
index e27863e86..952a7cd15 100644
--- a/daemon/inspect_fs_unix.ml
+++ b/daemon/inspect_fs_unix.ml
@@ -163,7 +163,7 @@ and distro_of_os_release_id = function
| "opencloudos" -> Some DISTRO_OPENCLOUDOS
| "tencentos" -> Some DISTRO_TENCENTOS
| "opensuse" -> Some DISTRO_OPENSUSE
- | s when String.is_prefix s "opensuse-" -> Some DISTRO_OPENSUSE
+ | s when String.starts_with "opensuse-" s -> Some DISTRO_OPENSUSE
| "pardus" -> Some DISTRO_PARDUS
| "pld" -> Some DISTRO_PLD_LINUX
| "rhel" -> Some DISTRO_RHEL
@@ -593,7 +593,7 @@ and check_hostname_from_file filename =
let hostname = Chroot.f chroot read_small_file filename in
- let keep_line line = line <> "" && not (String.is_prefix line "#") in
+ let keep_line line = line <> "" && not (String.starts_with "#" line) in
let lines = Option.map (List.filter keep_line) hostname in
match lines with
| None | Some [] -> None
@@ -699,11 +699,11 @@ and check_hostname_freebsd () =
let rec loop = function
| [] ->
raise Not_found
- | line :: _ when String.is_prefix line "hostname=\"" ||
- String.is_prefix line "hostname='" ->
+ | line :: _ when String.starts_with "hostname=\"" line ||
+ String.starts_with "hostname='" line ->
let len = String.length line - 10 - 1 in
String.sub line 10 len
- | line :: _ when String.is_prefix line "hostname=" ->
+ | line :: _ when String.starts_with "hostname=" line ->
let len = String.length line - 9 in
String.sub line 9 len
| _ :: lines ->
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
index 395a1c794..1ec7cb1c1 100644
--- a/daemon/inspect_fs_unix_fstab.ml
+++ b/daemon/inspect_fs_unix_fstab.ml
@@ -82,13 +82,13 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
* /dev/iso9660/FREEBSD_INSTALL can be found in FreeBSD's
* installation discs.
*)
- if (String.is_prefix spec "/dev/fd" &&
+ if (String.starts_with "/dev/fd" spec &&
String.length spec >= 8 && Char.isdigit spec.[7]) ||
- (String.is_prefix spec "/dev/cd" &&
+ (String.starts_with "/dev/cd" spec &&
String.length spec >= 8 && Char.isdigit spec.[7]) ||
spec = "/dev/floppy" ||
spec = "/dev/cdrom" ||
- String.is_prefix spec "/dev/iso9660/" then
+ String.starts_with "/dev/iso9660/" spec then
return None;
let mp = aug_get_noerrors aug (entry ^ "/file") in
@@ -103,20 +103,20 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
if verbose () then eprintf "check_fstab_entry: mp=%s\n%!" mp;
(* Ignore certain mountpoints. *)
- if String.is_prefix mp "/dev/" ||
+ if String.starts_with "/dev/" mp ||
mp = "/dev" ||
- String.is_prefix mp "/media/" ||
- String.is_prefix mp "/proc/" ||
+ String.starts_with "/media/" mp ||
+ String.starts_with "/proc/" mp ||
mp = "/proc" ||
- String.is_prefix mp "/selinux/" ||
+ String.starts_with "/selinux/" mp ||
mp = "/selinux" ||
- String.is_prefix mp "/sys/" ||
+ String.starts_with "/sys/" mp ||
mp = "/sys" then
return None;
let mountable =
(* Resolve UUID= and LABEL= to the actual device. *)
- if String.is_prefix spec "UUID=" then (
+ if String.starts_with "UUID=" spec then (
let uuid = String.sub spec 5 (String.length spec - 5) in
let uuid = shell_unquote uuid in
(* Just ignore the device if the UUID cannot be resolved. *)
@@ -125,7 +125,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
with
Failure _ -> return None
)
- else if String.is_prefix spec "LABEL=" then (
+ else if String.starts_with "LABEL=" spec then (
let label = String.sub spec 6 (String.length spec - 6) in
let label = shell_unquote label in
(* Just ignore the device if the label cannot be resolved. *)
@@ -135,7 +135,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
Failure _ -> return None
)
(* EFI partition UUIDs and labels. *)
- else if String.is_prefix spec "PARTUUID=" then (
+ else if String.starts_with "PARTUUID=" spec then (
let uuid = String.sub spec 9 (String.length spec - 9) in
let uuid = shell_unquote uuid in
(* Just ignore the device if the UUID cannot be resolved. *)
@@ -144,7 +144,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
with
Failure _ -> return None
)
- else if String.is_prefix spec "PARTLABEL=" then (
+ else if String.starts_with "PARTLABEL=" spec then (
let label = String.sub spec 10 (String.length spec - 10) in
let label = shell_unquote label in
(* Just ignore the device if the label cannot be resolved. *)
@@ -161,7 +161,7 @@ and check_fstab_entry md_map root_mountable os_type aug entry =
else if spec = "/dev/root" || (is_bsd && mp = "/") then
root_mountable
(* Resolve guest block device names. *)
- else if String.is_prefix spec "/dev/" then
+ else if String.starts_with "/dev/" spec then
resolve_fstab_device spec md_map os_type
(* In OpenBSD's fstab you can specify partitions
* on a disk by appending a period and a partition
@@ -347,7 +347,7 @@ and resolve_fstab_device spec md_map os_type =
eprintf "resolve_fstab_device: %s matched %s\n%!" spec what
in
- if String.is_prefix spec "/dev/mapper" then (
+ if String.starts_with "/dev/mapper" spec then (
debug_matching "/dev/mapper";
(* LVM2 does some strange munging on /dev/mapper paths for VGs and
* LVs which contain '-' character:
@@ -398,7 +398,7 @@ and resolve_fstab_device spec md_map os_type =
)
(* Ubuntu 22+ uses /dev/disk/by-uuid/ followed by a UUID. *)
- else if String.is_prefix spec "/dev/disk/by-uuid/" then (
+ else if String.starts_with "/dev/disk/by-uuid/" spec then (
debug_matching "diskbyuuid";
let uuid = String.sub spec 18 (String.length spec - 18) in
try
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
index 8bcda5eb8..dbaf4c362 100644
--- a/daemon/inspect_fs_windows.ml
+++ b/daemon/inspect_fs_windows.ml
@@ -94,11 +94,11 @@ and get_windows_systemroot_from_boot_ini boot_ini_path =
*)
let rec loop = function
| [] -> None
- | str :: rest when String.is_prefix str "[operating systems]" ->
+ | str :: rest when String.starts_with "[operating systems]" str ->
let rec loop2 = function
| [] -> []
- | str :: rest when String.is_prefix str "multi(" ||
- String.is_prefix str "scsi(" ->
+ | str :: rest when String.starts_with "multi(" str ||
+ String.starts_with "scsi(" str ->
str :: loop2 rest
| _ -> []
in
@@ -340,7 +340,7 @@ and get_drive_mappings h root data =
let device =
if typ = Hivex.REG_BINARY then (
if String.length blob >= 24 &&
- String.is_prefix blob "DMIO:ID:" (* GPT *) then
+ String.starts_with "DMIO:ID:" blob (* GPT *) then
map_registry_disk_blob_gpt (Lazy.force partitions) blob
else if String.length blob = 12 then
map_registry_disk_blob_mbr (Lazy.force devices) blob
diff --git a/daemon/ldm.ml b/daemon/ldm.ml
index 0aa9bc9de..2710f71c2 100644
--- a/daemon/ldm.ml
+++ b/daemon/ldm.ml
@@ -38,7 +38,7 @@ and list prefix =
let dir = Sys.readdir "/dev/mapper" in
let dir = Array.to_list dir in
let dir =
- List.filter (fun d -> String.is_prefix d prefix) dir in
+ List.filter (fun d -> String.starts_with prefix d) dir in
let dir = List.map ((^) "/dev/mapper/") dir in
List.sort compare dir
)
diff --git a/daemon/listfs.ml b/daemon/listfs.ml
index dfc5ad5a5..0139e927d 100644
--- a/daemon/listfs.ml
+++ b/daemon/listfs.ml
@@ -73,18 +73,18 @@ let rec list_filesystems () =
*)
and is_not_partitioned_device device =
let device =
- if String.is_prefix device "/dev/mapper/" then
+ if String.starts_with "/dev/mapper/" device then
Unix_utils.Realpath.realpath device
else
device in
- assert (String.is_prefix device "/dev/");
+ assert (String.starts_with "/dev/" device);
let dev_name = String.sub device 5 (String.length device - 5) in
let dev_dir = "/sys/block/" ^ dev_name in
(* Open the device's directory under /sys/block/<dev_name> and
* look for entries starting with <dev_name>, eg. /sys/block/sda/sda1
*)
- let is_device_partition file = String.is_prefix file dev_name in
+ let is_device_partition file = String.starts_with dev_name file in
let files = Array.to_list (Sys.readdir dev_dir) in
let has_partition = List.exists is_device_partition files in
@@ -157,7 +157,7 @@ and check_with_vfs_type ret device =
* for things which are members of some RAID or LVM set, most
* importantly "LVM2_member" which is a PV.
*)
- else if String.is_suffix vfs_type "_member" then
+ else if String.ends_with "_member" vfs_type then
()
(* Ignore encrypted partitions. These are also containers, as above. *)
diff --git a/daemon/md.ml b/daemon/md.ml
index b4ba3b442..f2679a02d 100644
--- a/daemon/md.ml
+++ b/daemon/md.ml
@@ -68,7 +68,7 @@ let md_detail md =
* remainder to lower case.
*)
let key =
- if String.is_prefix key "MD_" then
+ if String.starts_with "MD_" key then
String.sub key 3 (String.length key - 3)
else
key in
diff --git a/daemon/mount_utils.ml b/daemon/mount_utils.ml
index 57d3eb6cf..dab34d037 100644
--- a/daemon/mount_utils.ml
+++ b/daemon/mount_utils.ml
@@ -61,8 +61,8 @@ let rec umount_all () =
let mp = proc_unmangle_path mp in
(* Allow a mount directory like "/sysroot" or "/sysroot/..." *)
- if (sysroot_len > 0 && String.is_prefix mp sysroot) ||
- (String.is_prefix mp sysroot &&
+ if (sysroot_len > 0 && String.starts_with sysroot mp) ||
+ (String.starts_with sysroot mp &&
String.length mp > sysroot_len &&
mp.[sysroot_len] = '/') then
List.push_front mp mps
diff --git a/daemon/sfdisk.ml b/daemon/sfdisk.ml
index 3265d1e83..bdba9dc17 100644
--- a/daemon/sfdisk.ml
+++ b/daemon/sfdisk.ml
@@ -142,22 +142,22 @@ let part_get_gpt_attributes device partnum =
let out = String.sub out 1 (len-1) in
loop out acc
)
- else if String.is_prefix out "RequiredPartition" then (
+ else if String.starts_with "RequiredPartition" out 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 (
+ else if String.starts_with "NoBlockIOProtocol" out 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 (
+ else if String.starts_with "LegacyBIOSBootable" out 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 (
+ else if String.starts_with "GUID:" out then (
let out = String.sub out 5 (len-5) in
loop out acc
)
diff --git a/daemon/utils.ml b/daemon/utils.ml
index 71d1cf25c..40584c9f1 100644
--- a/daemon/utils.ml
+++ b/daemon/utils.ml
@@ -85,11 +85,11 @@ let commandr ?(fold_stdout_on_stderr = false) prog args =
if verbose () then (
if stdout <> "" then (
eprintf "command: %s: stdout:\n%s%!" prog stdout;
- if not (String.is_suffix stdout "\n") then eprintf "\n%!"
+ if not (String.ends_with "\n" stdout) then eprintf "\n%!"
);
if stderr <> "" then (
eprintf "command: %s: stderr:\n%s%!" prog stderr;
- if not (String.is_suffix stderr "\n") then eprintf "\n%!"
+ if not (String.ends_with "\n" stderr) then eprintf "\n%!"
)
);
@@ -114,7 +114,7 @@ let command ?fold_stdout_on_stderr prog args =
let split_device_partition dev =
(* Skip /dev/ prefix if present. *)
let dev =
- if String.is_prefix dev "/dev/" then
+ if String.starts_with "/dev/" dev then
String.sub dev 5 (String.length dev - 5)
else dev in
diff --git a/generator/daemon.ml b/generator/daemon.ml
index da5593ce1..6221531d2 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -511,7 +511,7 @@ let rec generate_daemon_caml_interface modname () =
generate_header OCamlStyle GPLv2plus;
let is_ocaml_module_function = function
- | { impl = OCaml m } when String.is_prefix m (modname ^ ".") -> true
+ | { impl = OCaml m } when String.starts_with (modname ^ ".") m -> true
| { impl = OCaml _ } -> false
| { impl = C } -> false
in
--
2.47.1

View File

@ -1,491 +0,0 @@
From 0ff73a42c7f4f309fbab11ea2e89ee6f0501367d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 11:35:13 +0100
Subject: [PATCH] generator: Implement struct FDevice type
This acts just like FString except that we do reverse device name
translation on it. The only use is in the 'pvs-full' API where we
will use it (in a subsequent commit) to reverse translate the pv_name
field (a device name) before returning it from the daemon.
Compare this to the 'pvs' API which also returns a list of device
names, but using the generator's 'RStructList (RDevice,...)' return
type, where RDevice is similarly reverse translated.
Note in the library-side bindings, because the name has already been
translated in the daemon, we just treat it exactly the same as
FString. The vast majority of this patch is this mechanical change.
---
generator/GObject.ml | 6 +++---
generator/OCaml.ml | 6 ++----
generator/XDR.ml | 2 +-
generator/c.ml | 20 +++++++++-----------
generator/csharp.ml | 2 +-
generator/daemon.ml | 30 ++++++++++++++++++++++++++----
generator/erlang.ml | 2 +-
generator/golang.ml | 4 ++--
generator/java.ml | 7 ++++---
generator/lua.ml | 2 +-
generator/perl.ml | 4 ++--
generator/php.ml | 4 ++--
generator/python.ml | 2 +-
generator/ruby.ml | 4 ++--
generator/rust.ml | 6 +++---
generator/types.ml | 1 +
generator/types.mli | 1 +
17 files changed, 62 insertions(+), 41 deletions(-)
diff --git a/generator/GObject.ml b/generator/GObject.ml
index b89db690f..87c5b33bf 100644
--- a/generator/GObject.ml
+++ b/generator/GObject.ml
@@ -206,7 +206,7 @@ let generate_gobject_struct_header filename typ cols () =
pr " * @%s: An unsigned 64-bit integer\n" n
| n, FInt64 ->
pr " * @%s: A signed 64-bit integer\n" n
- | n, FString ->
+ | n, (FString|FDevice) ->
pr " * @%s: A NULL-terminated string\n" n
| n, FBuffer ->
pr " * @%s: A GByteArray\n" n
@@ -231,7 +231,7 @@ let generate_gobject_struct_header filename typ cols () =
pr " guint64 %s;\n" n
| n, FInt64 ->
pr " gint64 %s;\n" n
- | n, FString ->
+ | n, (FString|FDevice) ->
pr " gchar *%s;\n" n
| n, FBuffer ->
pr " GByteArray *%s;\n" n
@@ -1228,7 +1228,7 @@ guestfs_session_close (GuestfsSession *session, GError **err)
| n, FUUID ->
pr "%smemcpy (%s%s, %s%s, sizeof (%s%s));\n"
indent dst n src n dst n
- | n, FString ->
+ | n, (FString|FDevice) ->
pr "%sif (%s%s) %s%s = g_strdup (%s%s);\n"
indent src n dst n src n
| n, FBuffer ->
diff --git a/generator/OCaml.ml b/generator/OCaml.ml
index 66ed5e1ae..d4dfe9ed0 100644
--- a/generator/OCaml.ml
+++ b/generator/OCaml.ml
@@ -512,7 +512,7 @@ copy_table (char * const * argv)
List.iteri (
fun i col ->
(match col with
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " v = caml_copy_string (%s->%s);\n" typ name
| name, FBuffer ->
pr " v = caml_alloc_initialized_string (%s->%s_len, %s->%s);\n"
@@ -839,9 +839,7 @@ and generate_ocaml_structure_decls () =
pr "type %s = {\n" typ;
List.iter (
function
- | name, FString -> pr " %s : string;\n" name
- | name, FBuffer -> pr " %s : string;\n" name
- | name, FUUID -> pr " %s : string;\n" name
+ | name, (FString|FDevice|FBuffer|FUUID) -> pr " %s : string;\n" name
| name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
| name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
| name, FChar -> pr " %s : char;\n" name
diff --git a/generator/XDR.ml b/generator/XDR.ml
index c5444b501..431959819 100644
--- a/generator/XDR.ml
+++ b/generator/XDR.ml
@@ -66,7 +66,7 @@ let generate_xdr () =
pr "struct guestfs_int_%s {\n" typ;
List.iter (function
| name, FChar -> pr " char %s;\n" name
- | name, FString -> pr " string %s<>;\n" name
+ | name, (FString|FDevice) -> pr " string %s<>;\n" name
| name, FBuffer -> pr " opaque %s<>;\n" name
| name, FUUID -> pr " opaque %s[32];\n" name
| name, FInt32 -> pr " int %s;\n" name
diff --git a/generator/c.ml b/generator/c.ml
index a51031eff..c6e5dd994 100644
--- a/generator/c.ml
+++ b/generator/c.ml
@@ -352,7 +352,7 @@ and generate_structs_pod () =
| name, FInt32 -> pr " int32_t %s;\n" name
| name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
| name, FInt64 -> pr " int64_t %s;\n" name
- | name, FString -> pr " char *%s;\n" name
+ | name, (FString|FDevice) -> pr " char *%s;\n" name
| name, FBuffer ->
pr " /* The next two fields describe a byte array. */\n";
pr " uint32_t %s_len;\n" name;
@@ -609,7 +609,7 @@ extern GUESTFS_DLL_PUBLIC void *guestfs_next_private (guestfs_h *g, const char *
List.iter (
function
| name, FChar -> pr " char %s;\n" name
- | name, FString -> pr " char *%s;\n" name
+ | name, (FString|FDevice) -> pr " char *%s;\n" name
| name, FBuffer ->
pr " uint32_t %s_len;\n" name;
pr " char *%s;\n" name
@@ -916,7 +916,7 @@ and generate_client_structs_compare () =
fun { s_name = typ; s_cols = cols } ->
let has_nonnumeric_cols =
let nonnumeric = function
- | _,(FString|FUUID|FBuffer) -> true
+ | _,(FString|FDevice|FUUID|FBuffer) -> true
| _,(FChar|FUInt32|FInt32|FUInt64|FBytes|FInt64|FOptPercent) -> false
in
List.exists nonnumeric cols in
@@ -932,7 +932,7 @@ and generate_client_structs_compare () =
);
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " r = strcmp (s1->%s, s2->%s);\n" name name;
pr " if (r != 0) return r;\n"
| name, FBuffer ->
@@ -1001,7 +1001,7 @@ and generate_client_structs_copy () =
fun { s_name = typ; s_cols = cols } ->
let has_boxed_cols =
let boxed = function
- | _,(FString|FBuffer) -> true
+ | _,(FString|FDevice|FBuffer) -> true
| _,(FChar|FUUID|FUInt32|FInt32|FUInt64|FBytes|FInt64|FOptPercent) ->
false
in
@@ -1014,8 +1014,7 @@ and generate_client_structs_copy () =
pr "{\n";
List.iter (
function
- | name, FString
- | name, FBuffer -> pr " free (s->%s);\n" name
+ | name, (FString|FDevice|FBuffer) -> pr " free (s->%s);\n" name
| _, FChar
| _, FUUID
| _, FUInt32
@@ -1038,8 +1037,7 @@ and generate_client_structs_copy () =
pr "\n";
List.iter (
function
- | name, FString
- | name, FBuffer -> pr " out->%s = NULL;\n" name
+ | name, (FString|FDevice|FBuffer) -> pr " out->%s = NULL;\n" name
| _, FChar
| _, FUUID
| _, FUInt32
@@ -1051,7 +1049,7 @@ and generate_client_structs_copy () =
) cols;
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " out->%s = strdup (inp->%s);\n" name name;
pr " if (out->%s == NULL) goto error;\n" name
| name, FBuffer ->
@@ -1234,7 +1232,7 @@ and generate_client_structs_print_c () =
);
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " fprintf (dest, \"%%s%s: %%s%%s\", indent, %s->%s, linesep);\n"
name typ name
| name, FUUID ->
diff --git a/generator/csharp.ml b/generator/csharp.ml
index d1999bcff..5c77a46b4 100644
--- a/generator/csharp.ml
+++ b/generator/csharp.ml
@@ -119,7 +119,7 @@ namespace Guestfs
List.iter (
function
| name, FChar -> pr " char %s;\n" name
- | name, FString -> pr " string %s;\n" name
+ | name, (FString | FDevice) -> pr " string %s;\n" name
| name, FBuffer ->
pr " uint %s_len;\n" name;
pr " string %s;\n" name
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 9f75f385a..e19fa07d2 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -442,15 +442,37 @@ let generate_daemon_stubs actions () =
pr " ret.%s.%s_val = r;\n" n n;
pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
name
- | RStruct (n, _) ->
+ | RStruct (n, typ) ->
+ (* XXX RStruct containing an FDevice field would require
+ * reverse device name translation. That is not implemented.
+ * See also RStructList immediately below this.
+ *)
+ let cols = (Structs.lookup_struct typ).s_cols in
+ assert (not (List.exists
+ (function (_, FDevice) -> true | _ -> false) cols));
pr " struct guestfs_%s_ret ret;\n" name;
pr " ret.%s = *r;\n" n;
pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
name;
pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
name
- | RStructList (n, _) ->
+ | RStructList (n, typ) ->
pr " struct guestfs_%s_ret ret;\n" name;
+ let cols = (Structs.lookup_struct typ).s_cols in
+ List.iter (
+ function
+ | (fname, FDevice) ->
+ pr " for (size_t i = 0; i < r->guestfs_int_%s_list_len; ++i) {\n"
+ typ;
+ pr " char *field = r->guestfs_int_%s_list_val[i].%s;\n"
+ typ fname;
+ pr " char *rr = reverse_device_name_translation (field);\n";
+ pr " if (!rr) abort ();\n";
+ pr " free (field);\n";
+ pr " r->guestfs_int_%s_list_val[i].%s = rr;\n" typ fname;
+ pr " }\n";
+ | _ -> ()
+ ) cols;
pr " ret.%s = *r;\n" n;
pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
name;
@@ -619,7 +641,7 @@ let generate_daemon_caml_stubs () =
fun i ->
pr " v = Field (retv, %d);\n" i;
function
- | n, (FString|FUUID) ->
+ | n, (FString|FDevice|FUUID) ->
pr " ret->%s = strdup (String_val (v));\n" n;
pr " if (ret->%s == NULL) return NULL;\n" n
| n, FBuffer ->
@@ -986,7 +1008,7 @@ let generate_daemon_lvm_tokenization () =
pr " if (*p) next = p+1; else next = NULL;\n";
pr " *p = '\\0';\n";
(match coltype with
- | FString ->
+ | FString | FDevice ->
pr " r->%s = strdup (tok);\n" name;
pr " if (r->%s == NULL) {\n" name;
pr " perror (\"strdup\");\n";
diff --git a/generator/erlang.ml b/generator/erlang.ml
index 65af75aaf..864b3ff04 100644
--- a/generator/erlang.ml
+++ b/generator/erlang.ml
@@ -286,7 +286,7 @@ and generate_erlang_structs () =
List.iteri (
fun i col ->
(match col with
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " if (ei_x_encode_string (buff, %s->%s) != 0) return -1;\n" typ name
| name, FBuffer ->
pr " if (ei_x_encode_string_len (buff, %s->%s, %s->%s_len) != 0) return -1;\n"
diff --git a/generator/golang.ml b/generator/golang.ml
index 0d6a92367..a5b39f5df 100644
--- a/generator/golang.ml
+++ b/generator/golang.ml
@@ -248,7 +248,7 @@ func return_hashtable (argv **C.char) map[string]string {
let n = String.capitalize_ascii n in
match field with
| FChar -> pr " %s byte\n" n
- | FString -> pr " %s string\n" n
+ | FString | FDevice -> pr " %s string\n" n
| FBuffer -> pr " %s []byte\n" n
| FUInt32 -> pr " %s uint32\n" n
| FInt32 -> pr " %s int32\n" n
@@ -267,7 +267,7 @@ func return_hashtable (argv **C.char) map[string]string {
let gon = String.capitalize_ascii n in
match field with
| FChar -> pr " r.%s = byte (c.%s)\n" gon n
- | FString -> pr " r.%s = C.GoString (c.%s)\n" gon n
+ | FString | FDevice -> pr " r.%s = C.GoString (c.%s)\n" gon n
| FBuffer ->
pr " r.%s = C.GoBytes (unsafe.Pointer (c.%s), C.int (c.%s_len))\n"
gon n n
diff --git a/generator/java.ml b/generator/java.ml
index 7a8c0016c..909db4530 100644
--- a/generator/java.ml
+++ b/generator/java.ml
@@ -560,6 +560,7 @@ public class %s {
List.iter (
function
| name, FString
+ | name, FDevice
| name, FUUID
| name, FBuffer -> pr " public String %s;\n" name
| name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
@@ -947,7 +948,7 @@ and generate_java_struct_return typ jtyp cols =
pr " jr = (*env)->AllocObject (env, cl);\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
| name, FUUID ->
@@ -997,7 +998,7 @@ and generate_java_struct_list_return typ jtyp cols =
fun (name, ftyp) ->
(* Get the field ID in 'fl'. *)
let java_field_type = match ftyp with
- | FString | FUUID | FBuffer -> "Ljava/lang/String;"
+ | FString | FDevice | FUUID | FBuffer -> "Ljava/lang/String;"
| FBytes | FUInt64 | FInt64 -> "J"
| FUInt32 | FInt32 -> "I"
| FOptPercent -> "F"
@@ -1007,7 +1008,7 @@ and generate_java_struct_list_return typ jtyp cols =
(* Assign the value to this field. *)
match ftyp with
- | FString ->
+ | FString | FDevice ->
pr " (*env)->SetObjectField (env, jfl, fl,\n";
pr " (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
| FUUID ->
diff --git a/generator/lua.ml b/generator/lua.ml
index 0d7e63be0..685645abf 100644
--- a/generator/lua.ml
+++ b/generator/lua.ml
@@ -824,7 +824,7 @@ push_event (lua_State *L, uint64_t event)
(match field with
| FChar ->
pr " lua_pushlstring (L, &v->%s, 1);\n" n
- | FString ->
+ | FString | FDevice ->
pr " lua_pushstring (L, v->%s);\n" n
| FBuffer ->
pr " lua_pushlstring (L, v->%s, v->%s_len);\n" n n
diff --git a/generator/perl.ml b/generator/perl.ml
index 0059d4c1d..17ed64d29 100644
--- a/generator/perl.ml
+++ b/generator/perl.ml
@@ -607,7 +607,7 @@ and generate_perl_struct_list_code typ cols name style =
pr " hv = newHV ();\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " (void) hv_store (hv, \"%s\", %d, newSVpv (r->val[i].%s, 0), 0);\n"
name (String.length name) name
| name, FUUID ->
@@ -645,7 +645,7 @@ and generate_perl_struct_code typ cols name style =
pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
match col with
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " PUSHs (sv_2mortal (newSVpv (r->%s, 0)));\n"
name
| name, FBuffer ->
diff --git a/generator/php.ml b/generator/php.ml
index df8470461..2b336f96f 100644
--- a/generator/php.ml
+++ b/generator/php.ml
@@ -616,7 +616,7 @@ and generate_php_struct_code typ cols =
pr " array_init (return_value);\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " guestfs_add_assoc_string (return_value, \"%s\", r->%s, 1);\n" name name
| name, FBuffer ->
pr " guestfs_add_assoc_stringl (return_value, \"%s\", r->%s, r->%s_len, 1);\n"
@@ -650,7 +650,7 @@ and generate_php_struct_list_code typ cols =
pr " array_init (z_elem);\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " guestfs_add_assoc_string (z_elem, \"%s\", r->val[c].%s, 1);\n"
name name
| name, FBuffer ->
diff --git a/generator/python.ml b/generator/python.ml
index 242721f33..86b70b2de 100644
--- a/generator/python.ml
+++ b/generator/python.ml
@@ -168,7 +168,7 @@ and generate_python_structs () =
pr " return NULL;\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " value = guestfs_int_py_fromstring (%s->%s);\n" typ name;
pr " if (value == NULL)\n";
pr " goto err;\n";
diff --git a/generator/ruby.ml b/generator/ruby.ml
index 0f63b82ed..f9787af69 100644
--- a/generator/ruby.ml
+++ b/generator/ruby.ml
@@ -526,7 +526,7 @@ and generate_ruby_struct_code typ cols =
pr " volatile VALUE rv = rb_hash_new ();\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
| name, FBuffer ->
pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
@@ -556,7 +556,7 @@ and generate_ruby_struct_list_code typ cols =
pr " volatile VALUE hv = rb_hash_new ();\n";
List.iter (
function
- | name, FString ->
+ | name, (FString|FDevice) ->
pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
| name, FBuffer ->
pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, r->val[i].%s_len));\n" name name name
diff --git a/generator/rust.ml b/generator/rust.ml
index 1f5cefa62..f4dcfd723 100644
--- a/generator/rust.ml
+++ b/generator/rust.ml
@@ -115,7 +115,7 @@ extern \"C\" {
List.iter (
function
| n, FChar -> pr " pub %s: i8,\n" n
- | n, FString -> pr " pub %s: String,\n" n
+ | n, (FString|FDevice) -> pr " pub %s: String,\n" n
| n, FBuffer -> pr " pub %s: Vec<u8>,\n" n
| n, FUInt32 -> pr " pub %s: u32,\n" n
| n, FInt32 -> pr " pub %s: i32,\n" n
@@ -130,7 +130,7 @@ extern \"C\" {
List.iter (
function
| n, FChar -> pr " %s: c_char,\n" n
- | n, FString -> pr " %s: *const c_char,\n" n
+ | n, (FString|FDevice) -> pr " %s: *const c_char,\n" n
| n, FBuffer ->
pr " %s_len: usize,\n" n;
pr " %s: *const c_char,\n" n;
@@ -154,7 +154,7 @@ extern \"C\" {
match x with
| n, FChar ->
pr "%s: (*raw).%s as i8,\n" n n;
- | n, FString ->
+ | n, (FString|FDevice) ->
pr "%s: char_ptr_to_string((*raw).%s)?,\n" n n;
| n, FBuffer ->
pr "%s: slice::from_raw_parts((*raw).%s as *const u8, (*raw).%s_len).to_vec(),\n" n n n
diff --git a/generator/types.ml b/generator/types.ml
index 76b699e78..7163da8d2 100644
--- a/generator/types.ml
+++ b/generator/types.ml
@@ -215,6 +215,7 @@ let defaults = { name = "";
type field =
| FChar (* C 'char' (really, a 7 bit byte). *)
| FString (* nul-terminated ASCII string, NOT NULL. *)
+ | FDevice (* device name, needs reverse transl. *)
| FBuffer (* opaque buffer of bytes, (char *, int) pair *)
| FUInt32
| FInt32
diff --git a/generator/types.mli b/generator/types.mli
index 7c549a35e..e8939370e 100644
--- a/generator/types.mli
+++ b/generator/types.mli
@@ -413,6 +413,7 @@ val defaults : action
type field =
| FChar (** C 'char' (really, a 7 bit byte). *)
| FString (** nul-terminated ASCII string, NOT NULL. *)
+ | FDevice (** device name, needs reverse transl. *)
| FBuffer (** opaque buffer of bytes, (char *, int) pair*)
| FUInt32
| FInt32
--
2.47.1

View File

@ -0,0 +1,57 @@
From 1c2b94f09521698ac35fc282f7e03b8cedbf094b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 May 2025 13:14:00 +0100
Subject: [PATCH] docs: Update release notes for 1.56
---
docs/guestfs-release-notes-1.56.pod | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/docs/guestfs-release-notes-1.56.pod b/docs/guestfs-release-notes-1.56.pod
index 12380df0d..bab14c139 100644
--- a/docs/guestfs-release-notes-1.56.pod
+++ b/docs/guestfs-release-notes-1.56.pod
@@ -18,6 +18,8 @@ Add support for TencentOS (Denise Cheng).
Inspection of Ubuntu 22+ guests that use a split F</usr> configuration
now works properly (thanks Jaroslav Spanko, Daniel Berrange).
+Inspecting guests that have duplicated root mountpoints now works.
+
=head2 API
New C<command_out> and C<sh_out> APIs which allow you to capture
@@ -66,6 +68,9 @@ dependencies (thanks Mohamed Akram).
When using C<./configure --disable-daemon> we no longer require augeas
and hivex (thanks Mohamed Akram).
+C<zfs-fuse> support has been dropped. The project is unmaintained
+upstream.
+
=head2 Internals
The tests were modified to use a set of common functions and remove
@@ -86,6 +91,9 @@ Some deprecated autoconf macros are no longer used.
We no longer emit a false warning about C<BLKDISCARD> when creating a
block device.
+Some internal OCaml List and String functions that we used have been
+replaced by ones from the OCaml stdlib, reducing code maintenance.
+
=head2 Bugs fixed
=begin comment
@@ -116,6 +124,11 @@ fstrim on a RHEL 7.2-created XFS filesystem does not trim as much as expected
Run fstrim twice to work around incorrect fstrim behaviour in RHEL 9 kernel
+=item L<https://issues.redhat.com/browse/RHEL-90168>
+
+virt-v2v fails with mount exited with status 32: mount: /sysroot:
+/dev/sda2 already mounted on /sysroot. [rhel-9.7]
+
=item L<https://github.com/libguestfs/libguestfs/issues/155>
1.54.0: gdisk/test-expand-gpt.pl fails
--
2.47.1

View File

@ -1,69 +0,0 @@
From 5a16d1120fb7b046974abde43b1c40250bfd1a95 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 11:50:37 +0100
Subject: [PATCH] generator: Use new FDevice type for the pvs-full pv_name
field
Remove the code which did explicit reverse device name translation,
and use the generator's code instead.
---
daemon/lvm.c | 29 +----------------------------
generator/structs.ml | 2 +-
2 files changed, 2 insertions(+), 29 deletions(-)
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 6d8d675db..261573882 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -146,34 +146,7 @@ do_vgs (void)
guestfs_int_lvm_pv_list *
do_pvs_full (void)
{
- guestfs_int_lvm_pv_list *r;
- size_t i;
- char *din, *dout;
-
- r = parse_command_line_pvs ();
- if (r == NULL)
- /* parse_command_line_pvs has already called reply_with_error */
- return NULL;
-
- /* The pv_name fields contain device names which must be reverse
- * translated. The problem here is that the generator does not have
- * a "FMountable" field type in types.mli.
- */
- for (i = 0; i < r->guestfs_int_lvm_pv_list_len; ++i) {
- din = r->guestfs_int_lvm_pv_list_val[i].pv_name;
- if (din) {
- dout = reverse_device_name_translation (din);
- if (!dout) {
- /* reverse_device_name_translation has already called reply_with_error*/
- /* XXX memory leak here */
- return NULL;
- }
- r->guestfs_int_lvm_pv_list_val[i].pv_name = dout;
- free (din);
- }
- }
-
- return r;
+ return parse_command_line_pvs ();
}
guestfs_int_lvm_vg_list *
diff --git a/generator/structs.ml b/generator/structs.ml
index e5ed71ecd..fcacade65 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -35,7 +35,7 @@ type struc = {
* we have to pull out the LVM columns separately here.
*)
let lvm_pv_cols = [
- "pv_name", FString;
+ "pv_name", FDevice;
"pv_uuid", FUUID;
"pv_fmt", FString;
"pv_size", FBytes;
--
2.47.1

View File

@ -1,4 +1,4 @@
From c3766f3353338baae501b95a4353d3040b12ff28 Mon Sep 17 00:00:00 2001
From dffc4f3fa73ee886a057cb450d12b1ee7ad25da9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 29 Jul 2013 14:47:56 +0100
Subject: [PATCH] RHEL: Disable unsupported remote drive protocols
@ -180,7 +180,7 @@ index e4e1021db..8419ce78a 100755
rm test-add-uri.out
rm test-add-uri.img
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index 34bd15ae6..f56bacff6 100644
index 53fa129f5..d6b1eb719 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -350,22 +350,6 @@ F<filename> is interpreted as a local file or device.

View File

@ -1,47 +0,0 @@
From 7a1ffd744b12c4c79fa1b78341ea714d831f4205 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 10:13:52 +0100
Subject: [PATCH] daemon: inspect: Resolve Ubuntu 22+ /dev/disk/by-uuid/ in
fstab
Ubuntu 22= uses /dev/disk/by-uuid/ followed by a filesystem UUID in
fstab entries. Resolve these to mountables.
A typical fstab entry looks like this:
# /boot was on /dev/vda2 during curtin installation
/dev/disk/by-uuid/b4e56462-5a64-4272-b76d-f5e58bd8f128 /boot ext4 defaults 0 1
The comment is generated by the installer and appears in the fstab.
This entry would be translated to /dev/sda2.
---
daemon/inspect_fs_unix_fstab.ml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
index 912ffee34..769959693 100644
--- a/daemon/inspect_fs_unix_fstab.ml
+++ b/daemon/inspect_fs_unix_fstab.ml
@@ -394,6 +394,19 @@ and resolve_fstab_device spec md_map os_type =
resolve_diskbyid part default
)
+ (* Ubuntu 22+ uses /dev/disk/by-uuid/ followed by a UUID. *)
+ else if String.is_prefix spec "/dev/disk/by-uuid/" then (
+ debug_matching "diskbyuuid";
+ let uuid = String.sub spec 18 (String.length spec - 18) in
+ try
+ (* Try a filesystem UUID. Unclear if this could be a partition UUID
+ * as well, but in the Ubuntu guest I tried it was an fs UUID XXX.
+ *)
+ Mountable.of_device (Findfs.findfs_uuid uuid)
+ with
+ Failure _ -> default
+ )
+
else if PCRE.matches re_freebsd_gpt spec then (
debug_matching "FreeBSD GPT";
(* group 1 (type) is not used *)
--
2.47.1

View File

@ -1,4 +1,4 @@
From 7fc7794f9fcf5f098b394d177be9f4281c3614f3 Mon Sep 17 00:00:00 2001
From e55a14036a8d2f7d6c00a55e9e781855bfc7e180 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 7 Jul 2015 09:28:03 -0400
Subject: [PATCH] RHEL: Reject use of libguestfs-winsupport features except for

View File

@ -1,44 +0,0 @@
From bcd6b3ec3a1038d840e832732b3910f939566436 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 13:19:17 +0100
Subject: [PATCH] generator: Fix implementation of FUUID for OCaml functions
This was implemented wrongly. In the XDR protocol, UUIDs are fixed
buffers of length 32. We can just use memcpy to copy from the OCaml
string to the UUID, but we have to ensure the string length returned
by OCaml is correct (if not we just assert, it's an internal error).
(It didn't even compile before, so we know it was never used).
---
generator/daemon.ml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/generator/daemon.ml b/generator/daemon.ml
index e19fa07d2..b23034fd7 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -606,6 +606,7 @@ let generate_daemon_caml_stubs () =
#include <string.h>
#include <inttypes.h>
#include <errno.h>
+#include <assert.h>
#include <caml/alloc.h>
#include <caml/callback.h>
@@ -641,9 +642,12 @@ let generate_daemon_caml_stubs () =
fun i ->
pr " v = Field (retv, %d);\n" i;
function
- | n, (FString|FDevice|FUUID) ->
+ | n, (FString|FDevice) ->
pr " ret->%s = strdup (String_val (v));\n" n;
pr " if (ret->%s == NULL) return NULL;\n" n
+ | n, FUUID ->
+ pr " assert (caml_string_length (v) == sizeof ret->%s);\n" n;
+ pr " memcpy (ret->%s, String_val (v), sizeof ret->%s);\n" n n
| n, FBuffer ->
pr " ret->%s_len = caml_string_length (v);\n" n;
pr " ret->%s = strdup (String_val (v));\n" n;
--
2.47.1

View File

@ -0,0 +1,27 @@
From b3c5978cdf583fba4dfc36f5ebc4d7248b5b0bfb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 13 May 2025 17:28:25 +0100
Subject: [PATCH] RHEL: appliance/init: Run depmod -a to rebuild kernel module
dependencies
---
appliance/init | 3 +++
1 file changed, 3 insertions(+)
diff --git a/appliance/init b/appliance/init
index 5d35a47dd..a3c5654ea 100755
--- a/appliance/init
+++ b/appliance/init
@@ -116,6 +116,9 @@ $UDEVD --daemon #--debug
udevadm trigger
udevadm settle --timeout=600
+# Recreate module dependencies (RHEL only)
+depmod -a
+
# Disk optimizations.
# Increase the SCSI timeout so we can read remote images.
shopt -s nullglob
--
2.47.1

View File

@ -1,45 +0,0 @@
From 3f9078261ce917231eb62575557b1c9fb076a91f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 13:57:30 +0100
Subject: [PATCH] Update common submodule
Pulls in these commits:
Richard W.M. Jones (2):
mltools: Fix memory leak in OCaml binding of libosinfo
mlstdutils: Implement String.implode
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common 347b13716..353b8474e:
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 212a151..086d66d 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -275,6 +275,12 @@ module String = struct
let map_chars f str =
List.map f (explode str)
+ let implode cs =
+ let n = List.length cs in
+ let b = Bytes.create n in
+ List.iteri (Bytes.unsafe_set b) cs;
+ Bytes.to_string b
+
let spaces n = String.make n ' '
let span str accept =
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index 72a2d44..39448fb 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -127,6 +127,8 @@ module String : sig
(** Explode a string into a list of characters. *)
val map_chars : (char -> 'a) -> string -> 'a list
(** Explode string, then map function over the characters. *)
+ val implode : char list -> string
+ (** Join list of characters into a single string. *)
val spaces : int -> string
(** [spaces n] creates a string of n spaces. *)
val span : string -> string -> int

View File

@ -1,660 +0,0 @@
From a73f248369d35249a9324a0e0df9f7ccd1420d3f Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 10:41:59 +0100
Subject: [PATCH] daemon: Rewrite {pvs,vgs,lvs}-full APIs in OCaml
These were previously written in very convoluted C which had to deal
with parsing the crazy output of the "lvm" command. In fact the
parsing was so complex that it was generated by the generator. It's
easier to do this in OCaml.
These are basically legacy APIs. They cannot be expanded and LVM
already supports many more fields. We should replace these with APIs
for getting single named fields from LVM.
---
.gitignore | 2 +-
daemon/Makefile.am | 5 +-
daemon/lvm.c | 22 ----
daemon/lvm_full.ml | 221 ++++++++++++++++++++++++++++++++++++++
docs/C_SOURCE_FILES | 1 -
generator/actions_core.ml | 3 +
generator/daemon.ml | 190 --------------------------------
generator/daemon.mli | 1 -
generator/main.ml | 2 -
generator/structs.ml | 4 +-
generator/structs.mli | 7 --
po/POTFILES | 1 -
12 files changed, 229 insertions(+), 230 deletions(-)
create mode 100644 daemon/lvm_full.ml
diff --git a/.gitignore b/.gitignore
index 9d59a80f1..81cd278cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -97,7 +97,7 @@ Makefile.in
/daemon/listfs.mli
/daemon/lvm.mli
/daemon/lvm_dm.mli
-/daemon/lvm-tokenization.c
+/daemon/lvm_full.mli
/daemon/md.mli
/daemon/mount.mli
/daemon/names.c
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index bb72c0244..90ece8461 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -22,7 +22,6 @@ BUILT_SOURCES = \
caml-stubs.c \
dispatch.c \
names.c \
- lvm-tokenization.c \
structs-cleanups.c \
structs-cleanups.h \
stubs-0.c \
@@ -52,6 +51,7 @@ generator_built = \
listfs.mli \
lvm.mli \
lvm_dm.mli \
+ lvm_full.mli \
md.mli \
mount.mli \
optgroups.ml \
@@ -152,7 +152,6 @@ guestfsd_SOURCES = \
luks.c \
lvm.c \
lvm-filter.c \
- lvm-tokenization.c \
md.c \
mkfs.c \
mknod.c \
@@ -298,6 +297,7 @@ SOURCES_MLI = \
listfs.mli \
lvm.mli \
lvm_dm.mli \
+ lvm_full.mli \
lvm_utils.mli \
md.mli \
mount.mli \
@@ -333,6 +333,7 @@ SOURCES_ML = \
ldm.ml \
link.ml \
lvm.ml \
+ lvm_full.ml \
lvm_utils.ml \
lvm_dm.ml \
findfs.ml \
diff --git a/daemon/lvm.c b/daemon/lvm.c
index 261573882..924c1ddb3 100644
--- a/daemon/lvm.c
+++ b/daemon/lvm.c
@@ -139,28 +139,6 @@ do_vgs (void)
return convert_lvm_output (out, NULL);
}
-/* These were so complex to implement that I ended up auto-generating
- * the code. That code is in stubs.c, and it is generated as usual
- * by generator.ml.
- */
-guestfs_int_lvm_pv_list *
-do_pvs_full (void)
-{
- return parse_command_line_pvs ();
-}
-
-guestfs_int_lvm_vg_list *
-do_vgs_full (void)
-{
- return parse_command_line_vgs ();
-}
-
-guestfs_int_lvm_lv_list *
-do_lvs_full (void)
-{
- return parse_command_line_lvs ();
-}
-
int
do_pvcreate (const char *device)
{
diff --git a/daemon/lvm_full.ml b/daemon/lvm_full.ml
new file mode 100644
index 000000000..d5653d2f0
--- /dev/null
+++ b/daemon/lvm_full.ml
@@ -0,0 +1,221 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2025 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.
+ *)
+
+(* This file implements the complicated lvs-full, vgs-full and pvs-full APIs
+ *
+ * XXX Deprecate these APIs are replace with APIs for getting single
+ * named fields from LVM. That will be slower but far more flexible
+ * and extensible.
+ *)
+
+open Unix
+open Printf
+
+open Std_utils
+
+open Utils
+
+(* LVM UUIDs are basically 32 byte strings with '-' inserted.
+ * Remove the '-' characters and check it's the right length.
+ *)
+let parse_uuid uuid =
+ let uuid' =
+ uuid |> String.explode |> List.filter ((<>) '-') |> String.implode in
+ if String.length uuid' <> 32 then
+ failwithf "lvm-full: parse_uuid: unexpected UUID format: %S" uuid;
+ uuid'
+
+(* Parse the percent fields. These can be empty. *)
+let parse_percent pc = if pc = "" then None else Some (float_of_string pc)
+
+(* XXX These must match generator/structs.ml *)
+let lvm_pv_cols = [
+ "pv_name"; (* FString *)
+ "pv_uuid"; (* FUUID *)
+ "pv_fmt"; (* FString *)
+ "pv_size"; (* FBytes *)
+ "dev_size"; (* FBytes *)
+ "pv_free"; (* FBytes *)
+ "pv_used"; (* FBytes *)
+ "pv_attr"; (* FString (* XXX *) *)
+ "pv_pe_count"; (* FInt64 *)
+ "pv_pe_alloc_count"; (* FInt64 *)
+ "pv_tags"; (* FString *)
+ "pe_start"; (* FBytes *)
+ "pv_mda_count"; (* FInt64 *)
+ "pv_mda_free"; (* FBytes *)
+]
+
+let tokenize_pvs = function
+ | [ pv_name; pv_uuid; pv_fmt; pv_size; dev_size; pv_free;
+ pv_used; pv_attr; pv_pe_count; pv_pe_alloc_count; pv_tags;
+ pe_start; pv_mda_count; pv_mda_free ] ->
+ { Structs.pv_name = pv_name;
+ pv_uuid = parse_uuid pv_uuid;
+ pv_fmt = pv_fmt;
+ pv_size = Int64.of_string pv_size;
+ dev_size = Int64.of_string dev_size;
+ pv_free = Int64.of_string pv_free;
+ pv_used = Int64.of_string pv_used;
+ pv_attr = pv_attr;
+ pv_pe_count = Int64.of_string pv_pe_count;
+ pv_pe_alloc_count = Int64.of_string pv_pe_alloc_count;
+ pv_tags = pv_tags;
+ pe_start = Int64.of_string pe_start;
+ pv_mda_count = Int64.of_string pv_mda_count;
+ pv_mda_free = Int64.of_string pv_mda_free }
+
+ | fields ->
+ failwithf "pvs-full: tokenize_pvs: unexpected number of fields: %d"
+ (List.length fields)
+
+(* XXX These must match generator/structs.ml *)
+let lvm_vg_cols = [
+ "vg_name"; (* FString *)
+ "vg_uuid"; (* FUUID *)
+ "vg_fmt"; (* FString *)
+ "vg_attr"; (* FString (* XXX *) *)
+ "vg_size"; (* FBytes *)
+ "vg_free"; (* FBytes *)
+ "vg_sysid"; (* FString *)
+ "vg_extent_size"; (* FBytes *)
+ "vg_extent_count"; (* FInt64 *)
+ "vg_free_count"; (* FInt64 *)
+ "max_lv"; (* FInt64 *)
+ "max_pv"; (* FInt64 *)
+ "pv_count"; (* FInt64 *)
+ "lv_count"; (* FInt64 *)
+ "snap_count"; (* FInt64 *)
+ "vg_seqno"; (* FInt64 *)
+ "vg_tags"; (* FString *)
+ "vg_mda_count"; (* FInt64 *)
+ "vg_mda_free"; (* FBytes *)
+]
+
+let tokenize_vgs = function
+ | [ vg_name; vg_uuid; vg_fmt; vg_attr; vg_size; vg_free; vg_sysid;
+ vg_extent_size; vg_extent_count; vg_free_count; max_lv;
+ max_pv; pv_count; lv_count; snap_count; vg_seqno; vg_tags;
+ vg_mda_count; vg_mda_free ] ->
+ { Structs.vg_name = vg_name;
+ vg_uuid = parse_uuid vg_uuid;
+ vg_fmt = vg_fmt;
+ vg_attr = vg_attr;
+ vg_size = Int64.of_string vg_size;
+ vg_free = Int64.of_string vg_free;
+ vg_sysid = vg_sysid;
+ vg_extent_size = Int64.of_string vg_extent_size;
+ vg_extent_count = Int64.of_string vg_extent_count;
+ vg_free_count = Int64.of_string vg_free_count;
+ max_lv = Int64.of_string max_lv;
+ max_pv = Int64.of_string max_pv;
+ pv_count = Int64.of_string pv_count;
+ lv_count = Int64.of_string lv_count;
+ snap_count = Int64.of_string snap_count;
+ vg_seqno = Int64.of_string vg_seqno;
+ vg_tags = vg_tags;
+ vg_mda_count = Int64.of_string vg_mda_count;
+ vg_mda_free = Int64.of_string vg_mda_free }
+
+ | fields ->
+ failwithf "pvs-full: tokenize_vgs: unexpected number of fields: %d"
+ (List.length fields)
+
+(* XXX These must match generator/structs.ml *)
+let lvm_lv_cols = [
+ "lv_name"; (* FString *)
+ "lv_uuid"; (* FUUID *)
+ "lv_attr"; (* FString (* XXX *) *)
+ "lv_major"; (* FInt64 *)
+ "lv_minor"; (* FInt64 *)
+ "lv_kernel_major"; (* FInt64 *)
+ "lv_kernel_minor"; (* FInt64 *)
+ "lv_size"; (* FBytes *)
+ "seg_count"; (* FInt64 *)
+ "origin"; (* FString *)
+ "snap_percent"; (* FOptPercent *)
+ "copy_percent"; (* FOptPercent *)
+ "move_pv"; (* FString *)
+ "lv_tags"; (* FString *)
+ "mirror_log"; (* FString *)
+ "modules"; (* FString *)
+]
+
+let tokenize_lvs = function
+ | [ lv_name; lv_uuid; lv_attr; lv_major; lv_minor; lv_kernel_major;
+ lv_kernel_minor; lv_size; seg_count; origin; snap_percent;
+ copy_percent; move_pv; lv_tags; mirror_log; modules ] ->
+ { Structs.lv_name = lv_name;
+ lv_uuid = parse_uuid lv_uuid;
+ lv_attr = lv_attr;
+ lv_major = Int64.of_string lv_major;
+ lv_minor = Int64.of_string lv_minor;
+ lv_kernel_major = Int64.of_string lv_kernel_major;
+ lv_kernel_minor = Int64.of_string lv_kernel_minor;
+ lv_size = Int64.of_string lv_size;
+ seg_count = Int64.of_string seg_count;
+ origin = origin;
+ snap_percent = parse_percent snap_percent;
+ copy_percent = parse_percent copy_percent;
+ move_pv = move_pv;
+ lv_tags = lv_tags;
+ mirror_log = mirror_log;
+ modules = modules }
+
+ | fields ->
+ failwithf "pvs-full: tokenize_vgs: unexpected number of fields: %d"
+ (List.length fields)
+
+let rec pvs_full () =
+ let out = run_lvm_command "pvs" lvm_pv_cols in
+ let lines = trim_and_split out in
+ let pvs = List.map tokenize_pvs lines in
+ pvs
+
+and vgs_full () =
+ let out = run_lvm_command "vgs" lvm_vg_cols in
+ let lines = trim_and_split out in
+ let vgs = List.map tokenize_vgs lines in
+ vgs
+
+and lvs_full () =
+ let out = run_lvm_command "lvs" lvm_lv_cols in
+ let lines = trim_and_split out in
+ let lvs = List.map tokenize_lvs lines in
+ lvs
+
+and run_lvm_command typ cols =
+ let cols = String.concat "," cols in
+ let cmd = [ typ; "-o"; cols;
+ "--unbuffered"; "--noheadings"; "--nosuffix";
+ "--separator"; "\r"; "--units"; "b" ] in
+ command "lvm" cmd
+
+and trim_and_split out =
+ (* Split the output into lines. *)
+ let lines = String.nsplit "\n" out in
+
+ (* LVM puts leading whitespace on each line so remove that. *)
+ let lines = List.map String.triml lines in
+
+ (* Ignore any blank lines. *)
+ let lines = List.filter ((<>) "") lines in
+
+ (* Split each line into fields. *)
+ let lines = List.map (String.nsplit "\r") lines in
+ lines
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 0038f95e4..cdfb1d615 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -111,7 +111,6 @@ daemon/link.c
daemon/ls.c
daemon/luks.c
daemon/lvm-filter.c
-daemon/lvm-tokenization.c
daemon/lvm.c
daemon/md.c
daemon/mkfs.c
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index 5e8de563a..34bd15ae6 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -1795,6 +1795,7 @@ See also C<guestfs_lvs_full>, C<guestfs_list_filesystems>." };
{ defaults with
name = "pvs_full"; added = (0, 0, 4);
style = RStructList ("physvols", "lvm_pv"), [], [];
+ impl = OCaml "Lvm_full.pvs_full";
optional = Some "lvm2";
shortdesc = "list the LVM physical volumes (PVs)";
longdesc = "\
@@ -1804,6 +1805,7 @@ of the L<pvs(8)> command. The \"full\" version includes all fields." };
{ defaults with
name = "vgs_full"; added = (0, 0, 4);
style = RStructList ("volgroups", "lvm_vg"), [], [];
+ impl = OCaml "Lvm_full.vgs_full";
optional = Some "lvm2";
shortdesc = "list the LVM volume groups (VGs)";
longdesc = "\
@@ -1813,6 +1815,7 @@ of the L<vgs(8)> command. The \"full\" version includes all fields." };
{ defaults with
name = "lvs_full"; added = (0, 0, 4);
style = RStructList ("logvols", "lvm_lv"), [], [];
+ impl = OCaml "Lvm_full.lvs_full";
optional = Some "lvm2";
shortdesc = "list the LVM logical volumes (LVs)";
longdesc = "\
diff --git a/generator/daemon.ml b/generator/daemon.ml
index b23034fd7..da5593ce1 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -951,196 +951,6 @@ let generate_daemon_dispatch () =
pr "}\n";
pr "\n"
-let generate_daemon_lvm_tokenization () =
- generate_header CStyle GPLv2plus;
-
- pr "\
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-#include <errno.h>
-#include <rpc/types.h>
-#include <rpc/xdr.h>
-
-#include \"daemon.h\"
-#include \"c-ctype.h\"
-#include \"guestfs_protocol.h\"
-#include \"actions.h\"
-#include \"optgroups.h\"
-
-";
-
- (* LVM columns and tokenization functions. *)
- (* XXX This generates crap code. We should rethink how we
- * do this parsing.
- *)
- List.iter (
- function
- | typ, cols ->
- pr "static const char lvm_%s_cols[] = \"%s\";\n"
- typ (String.concat "," (List.map fst cols));
- pr "\n";
-
- pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
- pr "{\n";
- pr " char *tok, *p, *next;\n";
- pr " size_t i, j;\n";
- pr "\n";
- (*
- pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
- pr "\n";
- *)
- pr " if (!str) {\n";
- pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
- pr " return -1;\n";
- pr " }\n";
- pr " if (!*str || c_isspace (*str)) {\n";
- pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
- pr " return -1;\n";
- pr " }\n";
- pr " tok = str;\n";
- List.iter (
- fun (name, coltype) ->
- pr " if (!tok) {\n";
- pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
- pr " return -1;\n";
- pr " }\n";
- pr " p = strchrnul (tok, '\\r');\n";
- pr " if (*p) next = p+1; else next = NULL;\n";
- pr " *p = '\\0';\n";
- (match coltype with
- | FString | FDevice ->
- pr " r->%s = strdup (tok);\n" name;
- pr " if (r->%s == NULL) {\n" name;
- pr " perror (\"strdup\");\n";
- pr " return -1;\n";
- pr " }\n"
- | FUUID ->
- pr " for (i = j = 0; i < 32; ++j) {\n";
- pr " if (tok[j] == '\\0') {\n";
- pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
- pr " return -1;\n";
- pr " } else if (tok[j] != '-')\n";
- pr " r->%s[i++] = tok[j];\n" name;
- pr " }\n";
- | FBytes ->
- pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
- pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
- pr " return -1;\n";
- pr " }\n";
- | FInt64 ->
- pr " if (sscanf (tok, \"%%\" SCNi64, &r->%s) != 1) {\n" name;
- pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
- pr " return -1;\n";
- pr " }\n";
- | FOptPercent ->
- pr " if (tok[0] == '\\0')\n";
- pr " r->%s = -1;\n" name;
- pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
- pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
- pr " return -1;\n";
- pr " }\n";
- | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
- assert false (* can never be an LVM column *)
- );
- pr " tok = next;\n";
- ) cols;
-
- pr " if (tok != NULL) {\n";
- pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
- pr " return -1;\n";
- pr " }\n";
- pr " return 0;\n";
- pr "}\n";
- pr "\n";
-
- pr "guestfs_int_lvm_%s_list *\n" typ;
- pr "parse_command_line_%ss (void)\n" typ;
- pr "{\n";
- pr " char *out, *err;\n";
- pr " char *p, *pend;\n";
- pr " int r, i;\n";
- pr " guestfs_int_lvm_%s_list *ret;\n" typ;
- pr " void *newp;\n";
- pr "\n";
- pr " ret = malloc (sizeof *ret);\n";
- pr " if (!ret) {\n";
- pr " reply_with_perror (\"malloc\");\n";
- pr " return NULL;\n";
- pr " }\n";
- pr "\n";
- pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
- pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
- pr "\n";
- pr " r = command (&out, &err,\n";
- pr " \"lvm\", \"%ss\",\n" typ;
- pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
- pr " \"--nosuffix\", \"--separator\", \"\\r\", \"--units\", \"b\", NULL);\n";
- pr " if (r == -1) {\n";
- pr " reply_with_error (\"%%s\", err);\n";
- pr " free (out);\n";
- pr " free (err);\n";
- pr " free (ret);\n";
- pr " return NULL;\n";
- pr " }\n";
- pr "\n";
- pr " free (err);\n";
- pr "\n";
- pr " /* Tokenize each line of the output. */\n";
- pr " p = out;\n";
- pr " i = 0;\n";
- pr " while (p) {\n";
- pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
- pr " if (pend) {\n";
- pr " *pend = '\\0';\n";
- pr " pend++;\n";
- pr " }\n";
- pr "\n";
- pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
- pr " p++;\n";
- pr "\n";
- pr " if (!*p) { /* Empty line? Skip it. */\n";
- pr " p = pend;\n";
- pr " continue;\n";
- pr " }\n";
- pr "\n";
- pr " /* Allocate some space to store this next entry. */\n";
- pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
- pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
- pr " if (newp == NULL) {\n";
- pr " reply_with_perror (\"realloc\");\n";
- pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
- pr " free (ret);\n";
- pr " free (out);\n";
- pr " return NULL;\n";
- pr " }\n";
- pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
- pr "\n";
- pr " /* Tokenize the next entry. */\n";
- pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
- pr " if (r == -1) {\n";
- pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
- pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
- pr " free (ret);\n";
- pr " free (out);\n";
- pr " return NULL;\n";
- pr " }\n";
- pr "\n";
- pr " ++i;\n";
- pr " p = pend;\n";
- pr " }\n";
- pr "\n";
- pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
- pr "\n";
- pr " free (out);\n";
- pr " return ret;\n";
- pr "}\n"
-
- ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
-
(* Generate a list of function names, for debugging in the daemon.. *)
let generate_daemon_names () =
generate_header CStyle GPLv2plus;
diff --git a/generator/daemon.mli b/generator/daemon.mli
index f65545302..849979451 100644
--- a/generator/daemon.mli
+++ b/generator/daemon.mli
@@ -23,7 +23,6 @@ val generate_daemon_caml_stubs : unit -> unit
val generate_daemon_caml_callbacks_ml : unit -> unit
val generate_daemon_caml_interface : string -> unit -> unit
val generate_daemon_dispatch : unit -> unit
-val generate_daemon_lvm_tokenization : unit -> unit
val generate_daemon_names : unit -> unit
val generate_daemon_optgroups_c : unit -> unit
val generate_daemon_optgroups_h : unit -> unit
diff --git a/generator/main.ml b/generator/main.ml
index 17bcef8b5..57285003b 100644
--- a/generator/main.ml
+++ b/generator/main.ml
@@ -147,8 +147,6 @@ Run it from the top source directory using the command
Daemon.generate_daemon_optgroups_ml;
output_to "daemon/optgroups.mli"
Daemon.generate_daemon_optgroups_mli;
- output_to "daemon/lvm-tokenization.c"
- Daemon.generate_daemon_lvm_tokenization;
output_to "daemon/structs-cleanups.c"
Daemon.generate_daemon_structs_cleanups_c;
output_to "daemon/structs-cleanups.h"
diff --git a/generator/structs.ml b/generator/structs.ml
index fcacade65..84db7fe84 100644
--- a/generator/structs.ml
+++ b/generator/structs.ml
@@ -31,9 +31,7 @@ type struc = {
s_unused : unit; (* Silences warning 23 when using 'defaults with ...' *)
}
-(* Because we generate extra parsing code for LVM command line tools,
- * we have to pull out the LVM columns separately here.
- *)
+(* XXX These must match daemon/lvm_full.ml *)
let lvm_pv_cols = [
"pv_name", FDevice;
"pv_uuid", FUUID;
diff --git a/generator/structs.mli b/generator/structs.mli
index 13bb0d5d3..c99086214 100644
--- a/generator/structs.mli
+++ b/generator/structs.mli
@@ -34,13 +34,6 @@ type struc = {
val structs : struc list
(** List of structures. *)
-val lvm_pv_cols : cols
-val lvm_vg_cols : cols
-val lvm_lv_cols : cols
-(** These are exported to the daemon code generator where they are
- used to generate code for parsing the output of commands like
- [lvs]. One day replace this with liblvm API calls. *)
-
val lookup_struct : string -> struc
(** Lookup a struct by name. *)
diff --git a/po/POTFILES b/po/POTFILES
index 75b040c06..d10f97106 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -90,7 +90,6 @@ daemon/link.c
daemon/ls.c
daemon/luks.c
daemon/lvm-filter.c
-daemon/lvm-tokenization.c
daemon/lvm.c
daemon/md.c
daemon/mkfs.c
--
2.47.1

View File

@ -1,72 +0,0 @@
From e43ca1912973b3ddfa73b09a4690aa8bb26e08af Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 16 Apr 2025 10:27:25 +0100
Subject: [PATCH] daemon: inspect: Resolve Ubuntu 22+
/dev/disk/by-id/dm-uuid-LVM-... in fstab
Linux + LVM supports device names like /dev/disk/by-id/dm-uuid-LVM-
followed by two concatenated UUIDs, firstly for the volume group and
secondly for the logical volume. We can reverse those to get the
device name (/dev/VG/LV).
fstab entries look like:
# / was on /dev/vg0/lv-0 during curtin installation
/dev/disk/by-id/dm-uuid-LVM-OzFWT6NHkstr1hcmrWRRMDGPn9xdZj1YOOycQ533186x288FdU6UubU3OlnWJz6D / ext4 defaults 0 1
# /usr was on /dev/vg0/lv-1 during curtin installation
/dev/disk/by-id/dm-uuid-LVM-OzFWT6NHkstr1hcmrWRRMDGPn9xdZj1YZu53m4ZssZ8Jeb3I14RAJwIj5YlHIb9P /usr ext4 defaults 0 1
The upshot of this fix is that we are now able to correctly inspect
and run virt-v2v on Ubuntu 22+ guests with split /usr. In particular,
we correctly map /etc/fstab entries like the above to LV device names,
which means that /usr merging now works correctly.
Reported-by: Jaroslav Spanko
Thanks: Daniel Berrange
Fixes: https://issues.redhat.com/browse/RHEL-87493
---
daemon/inspect_fs_unix_fstab.ml | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/daemon/inspect_fs_unix_fstab.ml b/daemon/inspect_fs_unix_fstab.ml
index 769959693..788b36caa 100644
--- a/daemon/inspect_fs_unix_fstab.ml
+++ b/daemon/inspect_fs_unix_fstab.ml
@@ -27,6 +27,7 @@ open Inspect_utils
let re_cciss = PCRE.compile "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$"
let re_diskbyid = PCRE.compile "^/dev/disk/by-id/.*-part(\\d+)$"
+let re_dmuuid = PCRE.compile "^/dev/disk/by-id/dm-uuid-LVM-([0-9a-zA-Z]{32})([0-9a-zA-Z]{32})$"
let re_freebsd_gpt = PCRE.compile "^/dev/(ada{0,1}|vtbd)(\\d+)p(\\d+)$"
let re_freebsd_mbr = PCRE.compile "^/dev/(ada{0,1}|vtbd)(\\d+)s(\\d+)([a-z])$"
let re_hurd_dev = PCRE.compile "^/dev/(h)d(\\d+)s(\\d+)$"
@@ -407,6 +408,26 @@ and resolve_fstab_device spec md_map os_type =
Failure _ -> default
)
+ (* Ubuntu 22+ uses /dev/disk/by-id/dm-uuid-LVM-... followed by a
+ * double UUID which identifies an LV. The first part of the UUID
+ * is the VG UUID. The second part is the LV UUID.
+ *)
+ else if PCRE.matches re_dmuuid spec then (
+ debug_matching "dmuuid";
+ let vg_uuid_spec = PCRE.sub 1 and lv_uuid_spec = PCRE.sub 2 in
+ try
+ (* Get the list of all VGs and LVs. *)
+ let vgs = Lvm_full.vgs_full () and lvs = Lvm_full.lvs_full () in
+ (* Find one VG & LV (hopefully) that matches the UUIDs. *)
+ let vg =
+ List.find (fun { Structs.vg_uuid } -> vg_uuid = vg_uuid_spec) vgs
+ and lv =
+ List.find (fun { Structs.lv_uuid } -> lv_uuid = lv_uuid_spec) lvs in
+ Mountable.of_device (sprintf "/dev/%s/%s" vg.vg_name lv.lv_name)
+ with
+ Failure _ | Not_found -> default
+ )
+
else if PCRE.matches re_freebsd_gpt spec then (
debug_matching "FreeBSD GPT";
(* group 1 (type) is not used *)
--
2.47.1

View File

@ -41,7 +41,7 @@ ExcludeArch: %{ix86}
Summary: Access and modify virtual machine disk images
Name: libguestfs
Epoch: 1
Version: 1.55.8
Version: 1.55.11
Release: 1%{?dist}.alma.1
License: LGPL-2.1-or-later
@ -82,19 +82,15 @@ Source8: copy-patches.sh
# https://github.com/libguestfs/libguestfs/commits/rhel-10.1
# Patches.
Patch0001: 0001-Translated-using-Weblate-Finnish.patch
Patch0002: 0002-Update-translation-files.patch
Patch0003: 0003-common-update-submodule.patch
Patch0004: 0004-daemon-inspect-Add-some-debugging-of-usr-merging.patch
Patch0005: 0005-generator-Implement-struct-FDevice-type.patch
Patch0006: 0006-generator-Use-new-FDevice-type-for-the-pvs-full-pv_n.patch
Patch0007: 0007-daemon-inspect-Resolve-Ubuntu-22-dev-disk-by-uuid-in.patch
Patch0008: 0008-generator-Fix-implementation-of-FUUID-for-OCaml-func.patch
Patch0009: 0009-Update-common-submodule.patch
Patch0010: 0010-daemon-Rewrite-pvs-vgs-lvs-full-APIs-in-OCaml.patch
Patch0011: 0011-daemon-inspect-Resolve-Ubuntu-22-dev-disk-by-id-dm-u.patch
Patch0012: 0012-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch
Patch0013: 0013-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
Patch0001: 0001-appliance-Remove-zfs-fuse.patch
Patch0002: 0002-Update-common-submodule.patch
Patch0003: 0003-Update-common-submodule.patch
Patch0004: 0004-ocaml-dep.sh.in-Remove-mlgettext-subdirectory.patch
Patch0005: 0005-Update-common-submodule.patch
Patch0006: 0006-docs-Update-release-notes-for-1.56.patch
Patch0007: 0007-RHEL-Disable-unsupported-remote-drive-protocols-RHBZ.patch
Patch0008: 0008-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
Patch0009: 0009-RHEL-appliance-init-Run-depmod-a-to-rebuild-kernel-m.patch
BuildRequires: autoconf, automake, libtool, gettext-devel
@ -121,7 +117,6 @@ BuildRequires: libselinux-utils
BuildRequires: libselinux-devel
BuildRequires: fuse, fuse-devel
BuildRequires: pcre2-devel
BuildRequires: file-devel
BuildRequires: libvirt-devel
BuildRequires: gperf
BuildRequires: rpm-devel
@ -283,12 +278,6 @@ BuildRequires: xz
%if !0%{?rhel}
BuildRequires: zerofree
%endif
%if !0%{?rhel}
%ifnarch %{arm} aarch64 s390 s390x riscv64
# http://zfs-fuse.net/issues/94
BuildRequires: zfs-fuse
%endif
%endif
BuildRequires: zstd
# Main package requires the appliance. This allows the appliance to
@ -383,9 +372,6 @@ For enhanced features, install:
libguestfs-ufs adds UFS (BSD) support
%endif
libguestfs-xfs adds XFS support
%if !0%{?rhel}
libguestfs-zfs adds ZFS support
%endif
For developers:
@ -516,20 +502,6 @@ This adds XFS support to %{name}. Install it if you want to process
disk images containing XFS.
%if !0%{?rhel}
%ifnarch %{arm} aarch64 s390 s390x riscv64
%package zfs
Summary: ZFS support for %{name}
License: GPL-2.0-or-later
Requires: %{name}%{?_isa} = %{epoch}:%{version}-%{release}
%description zfs
This adds ZFS support to %{name}. Install it if you want to process
disk images containing ZFS.
%endif
%endif
%package inspect-icons
Summary: Additional dependencies for inspecting guest icons
License: LGPL-2.1-or-later
@ -868,13 +840,6 @@ move_to strace zz-packages-rescue
move_to vim-minimal zz-packages-rescue
move_to rsync zz-packages-rsync
move_to xfsprogs zz-packages-xfs
%if !0%{?rhel}
%ifnarch %{arm} aarch64 s390 s390x riscv64
move_to zfs-fuse zz-packages-zfs
%endif
%else
remove zfs-fuse
%endif
%if !0%{?rhel}
# On Fedora you need kernel-modules-extra to be able to mount
@ -992,14 +957,6 @@ rm ocaml/html/.gitignore
%files xfs
%{_libdir}/guestfs/supermin.d/zz-packages-xfs
%if !0%{?rhel}
%ifnarch %{arm} aarch64 s390 s390x riscv64
%files zfs
%{_libdir}/guestfs/supermin.d/zz-packages-zfs
%endif
%endif
%files inspect-icons
# no files
@ -1121,17 +1078,21 @@ rm ocaml/html/.gitignore
%changelog
* Fri Apr 18 2025 Eduard Abdullin <eabdullin@almalinux.org> - 1:1.55.8-1.alma.1
* Wed May 14 2025 Eduard Abdullin <eabdullin@almalinux.org> - 1:1.55.11-1.alma.1
- Enable building for ppc64le
* Wed Apr 16 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.55.8-1
- Rebase to libguestfs 1.55.8
* Tue May 13 2025 Richard W.M. Jones <rjones@redhat.com> - 1:1.55.11-1
- Rebase to libguestfs 1.55.11
resolves: RHEL-81733
- Include host kernel information in libguestfs debugging output
resolves: RHEL-83026
- Fix virt-v2v conversion of split /usr Ubuntu 22+
resolves: RHEL-87622
- Remove dependencies on oUnit, flex, bison
- Remove dependencies on oUnit, flex, bison, file-devel
- Remove zfs-fuse (not used in RHEL)
- Fix gating test
- Fix inspection with duplicated root mountpoint
resolves: RHEL-90170
* Tue Nov 26 2024 Richard W.M. Jones <rjones@redhat.com> - 1:1.54.0-5
- Rebase to libguestfs 1.54.0

View File

@ -1,2 +1,2 @@
SHA512 (libguestfs-1.55.8.tar.gz) = 86510eb82c03381d432bca2ef1d077a971e0d0f27c7852a81dff0228bd3745748a19dff597defb948dd182568a0a949aaa37a1bbd619a96f976b4974f7c81c92
SHA512 (libguestfs-1.55.8.tar.gz.sig) = 08d64a4c1e885201961af6e48f95c7d2cccf6fa2ee5c50db5890b673f5e6397f09b89432a7ac1b5f6890424873b359c5f74d264bc2f243ed84fb1738c142cec1
SHA512 (libguestfs-1.55.11.tar.gz) = 3c2bf753ad1bf9dd1809f50e9e39dd154e97a33de7848b9d08feac23f543cc1100b928f1533a6ea4882125202793694c2917ea5561ccbd0c72154a7313cf9050
SHA512 (libguestfs-1.55.11.tar.gz.sig) = 42764c07832f02349f8d28482aa2aefd394b66b940d84765623491879b8960b22f567c51565f32dab204cc83aa8fa26b46fd181c10a43da05db29d2ee704deb0

View File

@ -0,0 +1,10 @@
#!/bin/bash -
set -e
set -x
# This only makes sure that libguestfs isn't totally broken.
# Fix libvirt.
systemctl restart virtqemud virtsecretd virtstoraged virtnetworkd
libguestfs-test-tool

View File

@ -5,9 +5,10 @@
- role: standard-test-basic
tags:
- classic
required_packages:
- libguestfs
- libvirt-daemon-kvm
tests:
- libguestfs-test-tool:
dir: .
run: libguestfs-test-tool
required_packages:
- libguestfs
run: ./run-libguestfs-test-tool.sh