import Oracle_OSS guestfs-tools-1.54.0-10.el10_2

This commit is contained in:
AlmaLinux RelEng Bot 2026-07-21 08:32:50 -04:00
parent 8deda3ce35
commit d1e19fa19f
54 changed files with 5764 additions and 1295 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
SOURCES/guestfs-tools-1.52.2.tar.gz
SOURCES/libguestfs.keyring
guestfs-tools-1.54.0.tar.gz
libguestfs.keyring

View File

@ -1,2 +0,0 @@
6eb02f4f70cb224548567ce7e4b67712c8ebb643 SOURCES/guestfs-tools-1.52.2.tar.gz
1bbc40f501a7fef9eef2a39b701a71aee2fea7c4 SOURCES/libguestfs.keyring

View File

@ -0,0 +1,34 @@
From 3a99e87bdee6c20a6286aa3e10bb2c2d896fb2ed Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 21 May 2025 15:02:44 +0100
Subject: [PATCH] docs: Move release note about GNU gettext to build section
Fixes: commit 9b7410c220f1111e6acef88efbbaee3fea4019b8
Updates: commit 80ce443e5eb7323e9b7b5cef30b8f7673ca51d67
(cherry picked from commit bf4fef4f2b45a2016c42094f8e4fe18abc8d90e2)
---
docs/guestfs-tools-release-notes-1.54.pod | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/guestfs-tools-release-notes-1.54.pod b/docs/guestfs-tools-release-notes-1.54.pod
index b44eb19a2..ab9062303 100644
--- a/docs/guestfs-tools-release-notes-1.54.pod
+++ b/docs/guestfs-tools-release-notes-1.54.pod
@@ -78,6 +78,8 @@ Some deprecated autoconf macros are no longer used.
Fix some issues when building on macOS (Mohamed Akram).
+Fix compatibility with GNU gettext 0.25.
+
=head2 Internals
The tests were modified to use a set of common functions and remove
@@ -87,8 +89,6 @@ nbdkit.
Some internal OCaml List and String functions that we used have been
replaced by ones from the OCaml stdlib, reducing code maintenance.
-Fix compatibility with GNU gettext 0.25.
-
=head2 Bugs fixed
=begin comment

View File

@ -1,4 +1,4 @@
From a0fbbc98f5fb069bcbf15a5a8ec51e4c778a2bd5 Mon Sep 17 00:00:00 2001
From 2eae3778a32b18944a6a561e10a35eae74fa11f0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 3 Jun 2025 08:29:57 +0100
Subject: [PATCH] builder: Update link to templates to use https

View File

@ -0,0 +1,32 @@
From b6401279c65497506eac2eaf61470bf6f49e89e7 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 16 Jun 2025 21:47:41 +0100
Subject: [PATCH] builder: Replace -cpu host with -cpu max in example
When KVM isn't present, some versions of qemu may print:
qemu-system-x86_64: Could not access KVM kernel module: No such file or directory
qemu-system-x86_64: failed to initialize kvm: No such file or directory
qemu-system-x86_64: falling back to tcg
qemu-system-x86_64: CPU model 'host' requires KVM or HVF
Use -cpu max instead which should work in both cases.
(cherry picked from commit 2e93abca5acaa69cd6fd08b70079e8f432539076)
---
builder/virt-builder.pod | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index 05bef1e05..ff0ec250c 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -1043,7 +1043,7 @@ following could be used to boot the virtual machine:
qemu-system-x86_64 \
-machine accel=kvm:tcg \
- -cpu host \
+ -cpu max \
-m 2048 \
-drive file=disk.img,format=raw,if=virtio

View File

@ -0,0 +1,143 @@
From 6a1e751d4b10ae1833ee18c0796306711e842e76 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 13 Aug 2025 16:51:39 +0100
Subject: [PATCH] customize: Fixes for selinux relabelling and Windows
firstboot
This updates the common submodule to add the fixes below. These
changes allow SELinux relabelling to work correctly on Linux split-
/usr configurations, and allow Windows firstboot scripts to be
deferred until after a reboot.
The SELinux relabelling change requires libguestfs >= 1.57.1 (for the
new guestfs_setfiles API).
Richard W.M. Jones (4):
mlstdutils: Add List.combine4 function
mlcustomize/SELinux_relabel.ml: Add comment
mlcustomize/SELinux_relabel.ml: Use new guestfs_setfiles API
mlcustomize/SELinux_relabel.ml: Relabel every mountpoint
Vadim Rozenfeld (1):
Modify the firstboot script to check the scripts execution return status
Fixes: https://issues.redhat.com/browse/RHEL-108174
Related: https://issues.redhat.com/browse/RHEL-100682
(cherry picked from commit ea0f9cf0743c3e50a996a9d7ec488d58a9312b11)
---
common | 2 +-
m4/guestfs-libraries.m4 | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
Submodule common d4a81e9dd..89f1eb2d3:
diff --git a/common/mlcustomize/SELinux_relabel.ml b/common/mlcustomize/SELinux_relabel.ml
index 2f3a09bf7..f1729e3f4 100644
--- a/common/mlcustomize/SELinux_relabel.ml
+++ b/common/mlcustomize/SELinux_relabel.ml
@@ -1,5 +1,5 @@
(* virt-customize
- * Copyright (C) 2016 Red Hat Inc.
+ * Copyright (C) 2016-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
@@ -24,6 +24,10 @@ open Printf
module G = Guestfs
+(* XXX A lot of this code could usefully be moved into
+ * [libguestfs.git/daemon/selinux.ml].
+ *)
+
let rec relabel (g : G.guestfs) =
(* Is the guest using SELinux? (Otherwise this is a no-op). *)
if is_selinux_guest g then (
@@ -109,5 +113,13 @@ and use_setfiles g =
g#copy_attributes ~all:true old_specfile specfile
);
+ (* Get the list of mountpoints, since setfiles does not cross
+ * filesystems (RHEL-108174).
+ *)
+ let mps = g#mountpoints () |>
+ List.map snd |> (* the list of directories *)
+ List.sort compare |> (* sort them for consistency *)
+ Array.of_list in
+
(* Relabel everything. *)
- g#selinux_relabel ~force:true specfile "/"
+ g#setfiles ~force:true specfile mps
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index 6aca4c34a..5f2642b06 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -305,13 +305,19 @@ if not exist \"%%scripts_done%%\" (
:: Pick the next script to run.
for %%%%f in (\"%%scripts%%\"\\*.bat) do (
echo running \"%%%%f\"
- move \"%%%%f\" \"%%scripts_done%%\"
- pushd \"%%scripts_done%%\"
+ pushd \"%%scripts%%\"
call \"%%%%~nf\"
set elvl=!errorlevel!
echo .... exit code !elvl!
popd
+ if !elvl! NEQ 249 (
+ echo Script succeeded, moving to scripts-done
+ move \"%%%%f\" \"%%scripts_done%%\"
+ ) else (
+ echo Script failed, will retry on next boot
+ )
+
:: Reboot the computer. This is necessary to free any locked
:: files which may prevent later scripts from running.
shutdown /r /t 0 /y
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 4850a5598..16032d992 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -80,6 +80,12 @@ module List = struct
| x::xs, y::ys, z::zs -> (x, y, z) :: combine3 xs ys zs
| _ -> invalid_arg "combine3"
+ let rec combine4 ws xs ys zs =
+ match ws, xs, ys, zs with
+ | [], [], [], [] -> []
+ | w::ws, x::xs, y::ys, z::zs -> (w, x, y, z) :: combine4 ws xs ys zs
+ | _ -> invalid_arg "combine4"
+
let rec assoc_lbl ?(cmp = Stdlib.compare) ~default x = function
| [] -> default
| (y, y') :: _ when cmp x y = 0 -> y'
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index fe6bf1a7c..a20e720c2 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -106,6 +106,11 @@ module List : sig
(** Like {!List.combine} but for triples.
All lists must be the same length. *)
+ val combine4 : 'a list -> 'b list -> 'c list -> 'd list ->
+ ('a * 'b * 'c * 'd) list
+ (** Like {!List.combine} but for 4-tuples.
+ All lists must be the same length. *)
+
val assoc_lbl : ?cmp:('a -> 'a -> int) -> default:'b -> 'a -> ('a * 'b) list -> 'b
(** Like {!assoc} but with a user-defined comparison function, and
instead of raising [Not_found], it returns the [~default] value. *)
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index c9fbf58b2..82e62d54f 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -19,8 +19,8 @@ dnl Any C libraries required by the libguestfs C library (not the daemon).
dnl Of course we need libguestfs.
dnl
-dnl We need libguestfs 1.55.6 for guestfs_sh_out.
-PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.55.6])
+dnl We need libguestfs 1.57.1 for guestfs_setfiles.
+PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.57.1])
printf "libguestfs version is "; $PKG_CONFIG --modversion libguestfs
dnl Test if it's GNU or XSI strerror_r.

View File

@ -0,0 +1,122 @@
From a01095308d22a5ab4d5858dfe0ee46f0b1bec28c Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 20 Aug 2025 10:34:24 +0100
Subject: [PATCH] Update common submodule
Pulls in this fix which should have no effect:
Richard W.M. Jones (1):
mlcustomize/firstboot.ml: Use quoted string literals for firstboot
(cherry picked from virt-v2v commit b7aadeac02ef326d542cd83e441b5a9d99ced793)
(cherry picked from commit 038b30fb08107487cdba4bc0dbabb33dbf75f4c3)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common 89f1eb2d3..7ecf3992b:
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index 5f2642b06..360c33d67 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -35,8 +35,7 @@ let sanitize_name =
module Linux = struct
let firstboot_dir = "/usr/lib/virt-sysprep"
- let firstboot_sh = sprintf "\
-#!/bin/sh -
+ let firstboot_sh = sprintf {|#!/bin/sh -
### BEGIN INIT INFO
# Provides: virt-sysprep
@@ -57,14 +56,14 @@ d=%s/scripts
d_done=%s/scripts-done
logfile=~root/virt-sysprep-firstboot.log
-echo \"$0\" \"$@\" 2>&1 | tee -a $logfile
-echo \"Scripts dir: $d\" 2>&1 | tee -a $logfile
+echo "$0" "$@" 2>&1 | tee -a $logfile
+echo "Scripts dir: $d" 2>&1 | tee -a $logfile
-if test \"$1\" = \"start\"
+if test "$1" = "start"
then
mkdir -p $d_done
for f in $d/* ; do
- if test -x \"$f\"
+ if test -x "$f"
then
# move the script to the 'scripts-done' directory, so it is not
# executed again at the next boot
@@ -75,7 +74,7 @@ then
done
rm -f $d_done/*
fi
-" firstboot_dir firstboot_dir
+|} firstboot_dir firstboot_dir
let systemd_target = "multi-user.target"
@@ -282,38 +281,37 @@ module Windows = struct
* XXX It would be better to use powershell here. For some ideas see
* https://github.com/HCK-CI/HLK-Setup-Scripts/
*)
- let firstboot_script = sprintf "\
-@echo off
+ let firstboot_script = sprintf {|@echo off
setlocal EnableDelayedExpansion
set firstboot=%s
-set log=%%firstboot%%\\log.txt
+set log=%%firstboot%%\log.txt
-set scripts=%%firstboot%%\\scripts
-set scripts_done=%%firstboot%%\\scripts-done
+set scripts=%%firstboot%%\scripts
+set scripts_done=%%firstboot%%\scripts-done
-call :main >> \"%%log%%\" 2>&1
+call :main >> "%%log%%" 2>&1
exit /b
:main
echo starting firstboot service
-if not exist \"%%scripts_done%%\" (
- mkdir \"%%scripts_done%%\"
+if not exist "%%scripts_done%%" (
+ mkdir "%%scripts_done%%"
)
:: Pick the next script to run.
-for %%%%f in (\"%%scripts%%\"\\*.bat) do (
- echo running \"%%%%f\"
- pushd \"%%scripts%%\"
- call \"%%%%~nf\"
+for %%%%f in ("%%scripts%%"\*.bat) do (
+ echo running "%%%%f"
+ pushd "%%scripts%%"
+ call "%%%%~nf"
set elvl=!errorlevel!
echo .... exit code !elvl!
popd
if !elvl! NEQ 249 (
echo Script succeeded, moving to scripts-done
- move \"%%%%f\" \"%%scripts_done%%\"
+ move "%%%%f" "%%scripts_done%%"
) else (
echo Script failed, will retry on next boot
)
@@ -329,8 +327,8 @@ for %%%%f in (\"%%scripts%%\"\\*.bat) do (
:: Fallthrough here if there are no scripts.
echo uninstalling firstboot service
-\"%%firstboot%%\\%s\" -s firstboot uninstall
-" firstboot_dir_win srvany in
+"%%firstboot%%\%s" -s firstboot uninstall
+|} firstboot_dir_win srvany in
g#write (firstboot_dir // "firstboot.bat")
(String.unix2dos firstboot_script);

View File

@ -0,0 +1,22 @@
From 9ee5fdf8146231087a461f4cddc0280db762c2f4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 1 Sep 2025 17:33:07 +0100
Subject: [PATCH] .gitignore: Ignore *.bak files
(cherry picked from commit cd5ea5cd63a11bc85077e6296021bd25b3c84662)
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 9c2e200e6..94f77ac74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
*.1
*.a
*.annot
+*.bak
*.cmi
*.cmo
*.cmx

View File

@ -0,0 +1,206 @@
From 0074de5f6eccb75dad814527813eba3524bb22e0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 1 Sep 2025 18:41:24 +0100
Subject: [PATCH] builder, sysprep: Use quoted string literals in a few places
This change was automated using the script in:
https://github.com/libguestfs/libguestfs/commit/02b64d5cec1ac0a6f7627d5489996de4474a67f6
However I manually only picked a few of the changes suggested
by the script.
(cherry picked from commit 624df48b3d14d2e5420d758a425bcae509cfe318)
---
builder/templates/make-template.ml | 62 ++++++++++++++---------------
sysprep/sysprep_operation_script.ml | 5 ++-
2 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/builder/templates/make-template.ml b/builder/templates/make-template.ml
index 73a55bd45..515c3da8b 100755
--- a/builder/templates/make-template.ml
+++ b/builder/templates/make-template.ml
@@ -535,8 +535,7 @@ and make_kickstart_common ks_filename os arch =
| _ -> bpf "install\n";
);
- bpf "\
-text
+ bpf {|text
reboot
lang en_US.UTF-8
keyboard us
@@ -544,7 +543,7 @@ network --bootproto dhcp
rootpw builder
firewall --enabled --ssh
timezone --utc America/New_York
-";
+|};
(match os with
| RHEL (ver, _) when ver <= 4 ->
@@ -586,19 +585,19 @@ mouse generic
| CentOS ((3|4|5|6) as major, _) | RHEL ((3|4|5|6) as major, _) ->
let bootfs = if major <= 5 then "ext2" else "ext4" in
let rootfs = if major <= 4 then "ext3" else "ext4" in
- bpf "\
+ bpf {|
zerombr
clearpart --all --initlabel
part /boot --fstype=%s --size=512 --asprimary
part swap --size=1024 --asprimary
part / --fstype=%s --size=1024 --grow --asprimary
-" bootfs rootfs;
+|} bootfs rootfs;
| Alma _ | CentOS _ | CentOSStream _ | RHEL _ | Fedora _ ->
- bpf "\
+ bpf {|
zerombr
clearpart --all --initlabel --disklabel=gpt
autopart --type=plain
-";
+|};
| _ -> assert false (* cannot happen, see caller *)
);
bpf "\n";
@@ -753,16 +752,16 @@ and make_unattend_iso os arch =
* file called \Windows\Panther\Setupact.log (NB:
* not \Windows\Setupact.log)
*)
- fprintf chan "
-<unattend xmlns=\"urn:schemas-microsoft-com:unattend\"
- xmlns:ms=\"urn:schemas-microsoft-com:asm.v3\"
- xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">
- <settings pass=\"windowsPE\">
- <component name=\"Microsoft-Windows-Setup\"
- publicKeyToken=\"31bf3856ad364e35\"
- language=\"neutral\"
- versionScope=\"nonSxS\"
- processorArchitecture=\"%s\">
+ fprintf chan {|
+<unattend xmlns="urn:schemas-microsoft-com:unattend"
+ xmlns:ms="urn:schemas-microsoft-com:asm.v3"
+ xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
+ <settings pass="windowsPE">
+ <component name="Microsoft-Windows-Setup"
+ publicKeyToken="31bf3856ad364e35"
+ language="neutral"
+ versionScope="nonSxS"
+ processorArchitecture="%s">
<UserData>
<AcceptEula>true</AcceptEula>
<ProductKey>
@@ -772,18 +771,18 @@ and make_unattend_iso os arch =
</UserData>
<DiskConfiguration>
- <Disk wcm:action=\"add\">
+ <Disk wcm:action="add">
<DiskID>0</DiskID>
<WillWipeDisk>true</WillWipeDisk>
<CreatePartitions>
<!-- System partition -->
- <CreatePartition wcm:action=\"add\">
+ <CreatePartition wcm:action="add">
<Order>1</Order>
<Type>Primary</Type>
<Size>300</Size>
</CreatePartition>
<!-- Windows partition -->
- <CreatePartition wcm:action=\"add\">
+ <CreatePartition wcm:action="add">
<Order>2</Order>
<Type>Primary</Type>
<Extend>true</Extend>
@@ -791,7 +790,7 @@ and make_unattend_iso os arch =
</CreatePartitions>
<ModifyPartitions>
<!-- System partition -->
- <ModifyPartition wcm:action=\"add\">
+ <ModifyPartition wcm:action="add">
<Order>1</Order>
<PartitionID>1</PartitionID>
<Label>System</Label>
@@ -799,7 +798,7 @@ and make_unattend_iso os arch =
<Active>true</Active>
</ModifyPartition>
<!-- Windows partition -->
- <ModifyPartition wcm:action=\"add\">
+ <ModifyPartition wcm:action="add">
<Order>2</Order>
<PartitionID>2</PartitionID>
<Label>Windows</Label>
@@ -828,11 +827,11 @@ and make_unattend_iso os arch =
</ImageInstall>
</component>
- <component name=\"Microsoft-Windows-International-Core-WinPE\"
- publicKeyToken=\"31bf3856ad364e35\"
- language=\"neutral\"
- versionScope=\"nonSxS\"
- processorArchitecture=\"%s\">
+ <component name="Microsoft-Windows-International-Core-WinPE"
+ publicKeyToken="31bf3856ad364e35"
+ language="neutral"
+ versionScope="nonSxS"
+ processorArchitecture="%s">
<SetupUILanguage>
<UILanguage>en-US</UILanguage>
</SetupUILanguage>
@@ -841,7 +840,7 @@ and make_unattend_iso os arch =
<UserLocale>en-US</UserLocale>
</component>
</settings>
-</unattend>"
+</unattend>|}
arch product_key arch;
close_out chan;
@@ -1411,14 +1410,13 @@ baseurl=%s
enabled=0
gpgcheck=0
keepcache=0
-" major major baseurl major major srpms;
+|} major major baseurl major major srpms;
(match optional with
| None -> ()
| Some (name, optionalbaseurl, optionalsrpms) ->
let lc_name = String.lowercase_ascii name in
- bpf "\
-
+ bpf {|
[rhel%d-%s]
name=RHEL %d Server %s
baseurl=%s
@@ -1432,7 +1430,7 @@ baseurl=%s
enabled=0
gpgcheck=0
keepcache=0
-" major lc_name major lc_name optionalbaseurl
+|} major lc_name major lc_name optionalbaseurl
major lc_name major lc_name optionalsrpms
)
) else (
diff --git a/sysprep/sysprep_operation_script.ml b/sysprep/sysprep_operation_script.ml
index fff5e4d51..a91cea26b 100644
--- a/sysprep/sysprep_operation_script.ml
+++ b/sysprep/sysprep_operation_script.ml
@@ -81,7 +81,7 @@ let rec script_perform (g : Guestfs.guestfs) root side_effects =
and run_scripts mp scripts =
let sh = "/bin/bash" in
let cmd =
- sprintf "\
+ sprintf {|
set -e
#set -x
cleanup ()
@@ -91,7 +91,8 @@ cleanup ()
guestunmount %s ||:
exit $status
}
-trap cleanup INT TERM QUIT EXIT ERR\n"
+trap cleanup INT TERM QUIT EXIT ERR
+|}
(Filename.quote mp) ^
String.concat "\n" scripts in
let args = [| sh; "-c"; cmd |] in

View File

@ -0,0 +1,26 @@
From cde27ebd4775cfa9a23a53a48b47303557bcb537 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 2 Sep 2025 09:05:27 +0100
Subject: [PATCH] builder/templates/make-template.ml: Fix quoting
Fix mistake introduced by manual editing of the previous commit.
Fixes: commit 624df48b3d14d2e5420d758a425bcae509cfe318
(cherry picked from commit 7e63b2142682582ec87bdd8c0d98bb22fcc0dabf)
---
builder/templates/make-template.ml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/builder/templates/make-template.ml b/builder/templates/make-template.ml
index 515c3da8b..a69d3ad3f 100755
--- a/builder/templates/make-template.ml
+++ b/builder/templates/make-template.ml
@@ -1394,7 +1394,7 @@ and make_rhel_yum_conf major minor arch =
sprintf "%s/AppStream/source/tree" topurl)
| _ -> assert false in
- bpf "\
+ bpf {|
# Yum configuration pointing to Red Hat servers.
[rhel%d]

View File

@ -0,0 +1,33 @@
From 1fca99c9bed60cd9a9c62826d4e6995052d0c5dd Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 2 Sep 2025 09:06:33 +0100
Subject: [PATCH] builder/templates/make-template.ml: Use quoted string
literals for regexps
(cherry picked from commit aafb271e8ffd961c529f90ef65df75a70102f0fc)
---
builder/templates/make-template.ml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/builder/templates/make-template.ml b/builder/templates/make-template.ml
index a69d3ad3f..f8b41209e 100755
--- a/builder/templates/make-template.ml
+++ b/builder/templates/make-template.ml
@@ -374,7 +374,7 @@ and os_of_string os ver =
eprintf "%s: unknown or unsupported OS (%s, %s)\n" prog os ver; exit 1
and parse_major_minor ver =
- let rex = Str.regexp "^\\([0-9]+\\)\\.\\([0-9]+\\)$" in
+ let rex = Str.regexp {|^\([0-9]+\)\.\([0-9]+\)$|} in
if Str.string_match rex ver 0 then (
int_of_string (Str.matched_group 1 ver),
int_of_string (Str.matched_group 2 ver)
@@ -1631,7 +1631,7 @@ and read_revision filename =
| None -> `No_file
| Some chan ->
let r = ref `No_revision in
- let rex = Str.regexp "^revision=\\([0-9]+\\)$" in
+ let rex = Str.regexp {|^revision=\([0-9]+\)$|} in
(try
let rec loop () =
let line = input_line chan in

View File

@ -0,0 +1,43 @@
From 7b2125b42535e6768d8f162d19463af4c4e8df1b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 2 Sep 2025 09:07:34 +0100
Subject: [PATCH] builder/templates/make-template.ml: Add +str and +unix for
OCaml 5
Removes these warnings:
File "_none_", line 1:
Alert ocaml_deprecated_auto_include:
OCaml's lib directory layout changed in 5.0. The str subdirectory has been
automatically added to the search path, but you should add -I +str to the
command-line to silence this alert (e.g. by adding str to the list of
libraries in your dune file, or adding use_str to your _tags file for
ocamlbuild, or using -package str for ocamlfind).
File "_none_", line 1:
Alert ocaml_deprecated_auto_include:
OCaml's lib directory layout changed in 5.0. The unix subdirectory has been
automatically added to the search path, but you should add -I +unix to the
command-line to silence this alert (e.g. by adding unix to the list of
libraries in your dune file, or adding use_unix to your _tags file for
ocamlbuild, or using -package unix for ocamlfind).
(cherry picked from commit 046309b31c22da5ac64feac12bcf4501377a8b3f)
---
builder/templates/make-template.ml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/builder/templates/make-template.ml b/builder/templates/make-template.ml
index f8b41209e..2ce803e2b 100755
--- a/builder/templates/make-template.ml
+++ b/builder/templates/make-template.ml
@@ -24,7 +24,9 @@
* shell scripts located in libguestfs.git/builder/website.
*)
+#directory "+str";;
#load "str.cma";;
+#directory "+unix";;
#load "unix.cma";;
#directory "+guestfs";; (* use globally installed guestfs *)
#load "mlguestfs.cma";;

View File

@ -0,0 +1,76 @@
From 68a3719888f36719cef8bcd7817ed634c4524012 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 12 Sep 2025 08:37:58 +0100
Subject: [PATCH] daemon, generator: Use power of 2 for initial size of
Hashtbl.create
Before 2011 it was recommended to use a prime number for the initial
size. In 2011 the OCaml hash table was reimplemented using a hash
function based on Murmur 3. Hashtbl.create now adjusts the initial
size to the next power of 2 (minimum 16). So replace obsolete
'Hashtbl.create 13' with 'Hashtbl.create 16'.
(cherry picked from commit 51f7dfa8612e8e273e3ef15eddd7a5714122cc57)
---
builder/builder.ml | 2 +-
builder/index_parser.ml | 4 ++--
resize/resize.ml | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/builder/builder.ml b/builder/builder.ml
index bbe2808f5..2df2fa5c7 100644
--- a/builder/builder.ml
+++ b/builder/builder.ml
@@ -46,7 +46,7 @@ let remove_duplicates index =
* (name, arch) tuples, so it possible to ignore duplicates,
* and versions with a lower revision.
*)
- let nseen = Hashtbl.create 13 in
+ let nseen = Hashtbl.create 16 in
List.iter (
fun (name, { Index.arch; revision }) ->
let id = name, arch in
diff --git a/builder/index_parser.ml b/builder/index_parser.ml
index 3e19e489e..2cb89488f 100644
--- a/builder/index_parser.ml
+++ b/builder/index_parser.ml
@@ -55,7 +55,7 @@ let get_index ~downloader ~sigchecker ?(template = false)
in
n, (find_arch fields)
) sections in
- let nseen = Hashtbl.create 13 in
+ let nseen = Hashtbl.create 16 in
List.iter (
fun (n, arch) ->
let id = n, arch in
@@ -71,7 +71,7 @@ let get_index ~downloader ~sigchecker ?(template = false)
(* Check for repeated fields. *)
List.iter (
fun (n, fields) ->
- let fseen = Hashtbl.create 13 in
+ let fseen = Hashtbl.create 16 in
List.iter (
fun (field, subkey, _) ->
let hashkey = (field, subkey) in
diff --git a/resize/resize.ml b/resize/resize.ml
index fffe2de77..707def8e9 100644
--- a/resize/resize.ml
+++ b/resize/resize.ml
@@ -630,7 +630,7 @@ read the man page virt-resize(1).
* that the user has asked to be ignored or deleted.
*)
let find_partition =
- let hash = Hashtbl.create 13 in
+ let hash = Hashtbl.create 16 in
List.iter (fun ({ p_name = name } as p) -> Hashtbl.add hash name p)
partitions;
fun ~option name ->
@@ -881,7 +881,7 @@ read the man page virt-resize(1).
surplus in
(* Mark the --lv-expand LVs. *)
- let hash = Hashtbl.create 13 in
+ let hash = Hashtbl.create 16 in
List.iter (fun ({ lv_name = name } as lv) -> Hashtbl.add hash name lv) lvs;
List.iter (

View File

@ -0,0 +1,123 @@
From abb56223e0a35c3e5d1158f32789c44c28bacf40 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 24 May 2025 13:27:00 +0100
Subject: [PATCH] builder: Build fedora-42 template
Thanks: Jeff Layton
---
builder/templates/fedora-42.index-fragment | 22 +++++++++
builder/templates/fedora-42.ks | 48 ++++++++++++++++++++
builder/templates/fedora-42.virt-install-cmd | 20 ++++++++
3 files changed, 90 insertions(+)
create mode 100644 builder/templates/fedora-42.index-fragment
create mode 100644 builder/templates/fedora-42.ks
create mode 100644 builder/templates/fedora-42.virt-install-cmd
diff --git a/builder/templates/fedora-42.index-fragment b/builder/templates/fedora-42.index-fragment
new file mode 100644
index 000000000..6d21b742c
--- /dev/null
+++ b/builder/templates/fedora-42.index-fragment
@@ -0,0 +1,22 @@
+[fedora-42]
+name=Fedora® 42 Server
+osinfo=fedora42
+arch=x86_64
+file=fedora-42.xz
+checksum[sha512]=dda921f3c522da8d8a67e31948260f52a9aa5bdeca4382a5c557635d77ad91d11b9aded70a225f59503b268ec73815ceac2eac5b70c1d47f22056febdd9da6bb
+format=raw
+size=6442450944
+compressed_size=927728896
+expand=/dev/sda3
+notes=Fedora® 42 Server
+
+ This Fedora image contains only unmodified @Core group packages.
+
+ Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+ Source and further information is available from http://fedoraproject.org/
+
+ This template was generated by a script in the libguestfs source tree:
+ builder/templates/make-template.ml
+ Associated files used to prepare this template can be found in the
+ same directory.
+
diff --git a/builder/templates/fedora-42.ks b/builder/templates/fedora-42.ks
new file mode 100644
index 000000000..17e2e3f15
--- /dev/null
+++ b/builder/templates/fedora-42.ks
@@ -0,0 +1,48 @@
+# Kickstart file for fedora-42
+# Generated by libguestfs.git/builder/templates/make-template.ml
+
+text
+reboot
+lang en_US.UTF-8
+keyboard us
+network --bootproto dhcp
+rootpw builder
+firewall --enabled --ssh
+timezone --utc America/New_York
+selinux --enforcing
+
+bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+
+
+zerombr
+clearpart --all --initlabel --disklabel=gpt
+autopart --type=plain
+
+# Halt the system once configuration has finished.
+poweroff
+
+%packages
+@core
+%end
+
+%post
+# Ensure the installation is up-to-date.
+dnf -y --best upgrade
+# This required otherwise the kernel will not be bootable, see
+# https://bugzilla.redhat.com/show_bug.cgi?id=1911177
+# https://bugzilla.redhat.com/show_bug.cgi?id=1945835#c24
+grub2-mkconfig -o '/etc/grub2.cfg'
+# Enable Xen domU support.
+pushd /etc/dracut.conf.d
+echo 'add_drivers+=" xen:vbd xen:vif "' > virt-builder-xen-drivers.conf
+popd
+# To make dracut config changes permanent, we need to rerun dracut.
+# Rerun dracut for the installed kernel (not the running kernel).
+# See commit 0fa52e4e45d80874bc5ea5f112f74be1d3f3472f and
+# https://www.redhat.com/archives/libguestfs/2014-June/thread.html#00045
+KERNEL_VERSION="$(rpm -q kernel --qf '%{version}-%{release}.%{arch}\n' |
+ sort -V | tail -1)"
+dracut -f /boot/initramfs-$KERNEL_VERSION.img $KERNEL_VERSION
+%end
+
+# EOF
diff --git a/builder/templates/fedora-42.virt-install-cmd b/builder/templates/fedora-42.virt-install-cmd
new file mode 100644
index 000000000..2a3256bbd
--- /dev/null
+++ b/builder/templates/fedora-42.virt-install-cmd
@@ -0,0 +1,20 @@
+# This is the virt-install command which was used to create
+# the virt-builder template 'fedora-42'
+# NB: This file is generated for documentation purposes ONLY!
+# This script was never run, and is not intended to be run.
+
+'virt-install' \
+ '--transient' \
+ '--name=tmp-oeg15xnl' \
+ '--ram=4096' \
+ '--arch=x86_64' \
+ '--cpu=host' \
+ '--vcpus=4' \
+ '--os-variant=fedora34' \
+ '--initrd-inject=fedora-42.ks' \
+ '--extra-args=inst.ks=file:/fedora-42.ks console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH' \
+ '--disk=/home/rjones/d/guestfs-tools/builder/templates/tmp-oeg15xnl.img,size=6,format=raw' \
+ '--location=https://lon.mirror.rackspace.com/fedora/releases/42/Server/x86_64/os/' \
+ '--serial=pty' \
+ '--nographics'
+

View File

@ -0,0 +1,61 @@
From 2d808c89eee6369df62b3afe16681a41ca42e0b9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Sat, 20 Sep 2025 17:20:25 +0100
Subject: [PATCH] Update common submodule
Richard W.M. Jones (3):
mlstdutils: Export List.find_opt
daemon, generator: Use power of 2 for initial size of Hashtbl.create
mlcustomize/inject_virtio_win.ml: Use viostor.inf instead of guestor
See-also: https://github.com/libguestfs/libguestfs-common/pull/17
(cherry picked from commit 13bcff3c2ca3e7ad355527a13b3aa2941ec1ff5b)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common 7ecf3992b..da55dc4d7:
diff --git a/common/mlcustomize/customize_run.ml b/common/mlcustomize/customize_run.ml
index ff719f4ec..64afd3ab5 100644
--- a/common/mlcustomize/customize_run.ml
+++ b/common/mlcustomize/customize_run.ml
@@ -97,7 +97,7 @@ let run (g : G.guestfs) root (ops : ops) =
) in
(* Store the passwords and set them all at the end. *)
- let passwords = Hashtbl.create 13 in
+ let passwords = Hashtbl.create 16 in
let set_password user pw =
if Hashtbl.mem passwords user then
error (f_"multiple --root-password/--password options set the \
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
index b26b14d34..114df0641 100644
--- a/common/mlcustomize/inject_virtio_win.ml
+++ b/common/mlcustomize/inject_virtio_win.ml
@@ -310,8 +310,13 @@ and ddb_regedits inspect drv_name drv_pciid =
* one must add keys into the DriverDatabase.
*)
+ let winarch =
+ match inspect.i_arch with
+ | "i386" -> "x86" | "x86_64" -> "amd64"
+ | _ -> assert false in
+
let drv_inf = "guestor.inf" in
- let drv_inf_label = drv_inf ^ "_tmp" in
+ let drv_inf_label = sprintf "%s_%s_0000000000000000" drv_inf winarch in
let drv_config = "guestor_conf" in
[
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index a20e720c2..6c1911da8 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -46,6 +46,7 @@ module List : sig
val mem : 'a -> 'a list -> bool
val memq : 'a -> 'a list -> bool
val find : ('a -> bool) -> 'a list -> 'a
+ val find_opt : ('a -> bool) -> 'a list -> 'a option
val filter : ('a -> bool) -> 'a list -> 'a list
val find_all : ('a -> bool) -> 'a list -> 'a list
val partition : ('a -> bool) -> 'a list -> 'a list * 'a list

View File

@ -0,0 +1,427 @@
From 5ed99959b689fc6fa287d9c6100e92a18bc1c9be Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 14 Oct 2025 14:07:40 -0400
Subject: [PATCH] common: update submodule
Cole Robinson (1):
mlcustomize: deprecate and remove --sm-* options
Signed-off-by: Cole Robinson <crobinso@redhat.com>
(cherry picked from commit 57b225d8d324d15d79fab2ccc6944868c1168a42)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common da55dc4d7..90399dd18:
diff --git a/common/mlcustomize/Makefile.am b/common/mlcustomize/Makefile.am
index 6e03bfea3..351524c80 100644
--- a/common/mlcustomize/Makefile.am
+++ b/common/mlcustomize/Makefile.am
@@ -47,7 +47,6 @@ SOURCES_MLI = \
random_seed.mli \
SELinux_relabel.mli \
ssh_key.mli \
- subscription_manager.mli \
timezone.mli
# This list must be in dependency order.
@@ -58,7 +57,6 @@ SOURCES_ML = \
perl_edit.ml \
random_seed.ml \
ssh_key.ml \
- subscription_manager.ml \
timezone.ml \
crypt.ml \
password.ml \
diff --git a/common/mlcustomize/customize-options.pod b/common/mlcustomize/customize-options.pod
index 157145ebc..c8de3953c 100644
--- a/common/mlcustomize/customize-options.pod
+++ b/common/mlcustomize/customize-options.pod
@@ -392,35 +392,6 @@ It cannot delete directories, only regular files.
This is a compatibility option that does nothing.
-=item B<--sm-attach> SELECTOR
-
-Attach to a pool using C<subscription-manager>.
-
-See L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of
-the C<SELECTOR> field.
-
-=item B<--sm-credentials> SELECTOR
-
-Set the credentials for C<subscription-manager>.
-
-See L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of
-the C<SELECTOR> field.
-
-=item B<--sm-register>
-
-Register the guest using C<subscription-manager>.
-
-This requires credentials being set using I<--sm-credentials>.
-
-=item B<--sm-remove>
-
-Remove all the subscriptions from the guest using
-C<subscription-manager>.
-
-=item B<--sm-unregister>
-
-Unregister the guest using C<subscription-manager>.
-
=item B<--ssh-inject> USER[:SELECTOR]
Inject an ssh key so the given C<USER> will be able to log in over
diff --git a/common/mlcustomize/customize-synopsis.pod b/common/mlcustomize/customize-synopsis.pod
index 957de8cf2..f5eeb69dd 100644
--- a/common/mlcustomize/customize-synopsis.pod
+++ b/common/mlcustomize/customize-synopsis.pod
@@ -8,11 +8,10 @@
[--install PKG,PKG..] [--link TARGET:LINK[:LINK..]] [--mkdir DIR]
[--move SOURCE:DEST] [--password USER:SELECTOR]
[--root-password SELECTOR] [--run SCRIPT]
- [--run-command 'CMD+ARGS'] [--scrub FILE] [--sm-attach SELECTOR]
- [--sm-register] [--sm-remove] [--sm-unregister]
+ [--run-command 'CMD+ARGS'] [--scrub FILE]
[--ssh-inject USER[:SELECTOR]] [--tar-in TARFILE:REMOTEDIR]
[--timezone TIMEZONE] [--touch FILE] [--truncate FILE]
[--truncate-recursive PATH] [--uninstall PKG,PKG..] [--update]
[--upload FILE:DEST] [--write FILE:CONTENT] [--no-logfile]
[--password-crypto md5|sha256|sha512] [--no-selinux-relabel]
- [--selinux-relabel] [--sm-credentials SELECTOR]
+ [--selinux-relabel]
diff --git a/common/mlcustomize/customize_cmdline.ml b/common/mlcustomize/customize_cmdline.ml
index 7451f1325..786f4ee49 100644
--- a/common/mlcustomize/customize_cmdline.ml
+++ b/common/mlcustomize/customize_cmdline.ml
@@ -85,14 +85,6 @@ and op = [
(* --run-command 'CMD+ARGS' *)
| `Scrub of string
(* --scrub FILE *)
- | `SMAttach of Subscription_manager.sm_pool
- (* --sm-attach SELECTOR *)
- | `SMRegister
- (* --sm-register *)
- | `SMRemove
- (* --sm-remove *)
- | `SMUnregister
- (* --sm-unregister *)
| `SSHInject of string * Ssh_key.ssh_key_selector
(* --ssh-inject USER[:SELECTOR] *)
| `TarIn of string * string
@@ -123,8 +115,6 @@ and flags = {
(* --no-selinux-relabel *)
selinux_relabel_ignored : bool;
(* --selinux-relabel *)
- sm_credentials : Subscription_manager.sm_credentials option;
- (* --sm-credentials SELECTOR *)
}
type argspec = Getopt.keys * Getopt.spec * Getopt.doc
@@ -135,7 +125,6 @@ let rec argspec ?(v2v = false) () =
let password_crypto = ref None in
let no_selinux_relabel = ref false in
let selinux_relabel_ignored = ref false in
- let sm_credentials = ref None in
let rec get_ops () = {
ops = List.rev !ops;
@@ -146,7 +135,6 @@ let rec argspec ?(v2v = false) () =
password_crypto = !password_crypto;
no_selinux_relabel = !no_selinux_relabel;
selinux_relabel_ignored = !selinux_relabel_ignored;
- sm_credentials = !sm_credentials;
}
in
@@ -386,35 +374,6 @@ let rec argspec ?(v2v = false) () =
s_"Scrub a file"
),
Some "FILE", "Scrub a file from the guest. This is like I<--delete> except that:\n\n=over 4\n\n=item *\n\nIt scrubs the data so a guest could not recover it.\n\n=item *\n\nIt cannot delete directories, only regular files.\n\n=back", false;
- (
- [ L"sm-attach" ],
- Getopt.String (
- s_"SELECTOR",
- fun s ->
- let sel = Subscription_manager.parse_pool_selector s in
- List.push_front (`SMAttach sel) ops
- ),
- s_"Attach to a subscription-manager pool"
- ),
- Some "SELECTOR", "Attach to a pool using C<subscription-manager>.\n\nSee L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of\nthe C<SELECTOR> field.", false;
- (
- [ L"sm-register" ],
- Getopt.Unit (fun () -> List.push_front `SMRegister ops),
- s_"Register using subscription-manager"
- ),
- None, "Register the guest using C<subscription-manager>.\n\nThis requires credentials being set using I<--sm-credentials>.", false;
- (
- [ L"sm-remove" ],
- Getopt.Unit (fun () -> List.push_front `SMRemove ops),
- s_"Remove all the subscriptions"
- ),
- None, "Remove all the subscriptions from the guest using\nC<subscription-manager>.", false;
- (
- [ L"sm-unregister" ],
- Getopt.Unit (fun () -> List.push_front `SMUnregister ops),
- s_"Unregister using subscription-manager"
- ),
- None, "Unregister the guest using C<subscription-manager>.", false;
(
[ L"ssh-inject" ],
Getopt.String (
@@ -529,16 +488,6 @@ let rec argspec ?(v2v = false) () =
s_"Compatibility option doing nothing"
),
None, "This is a compatibility option that does nothing.", false;
- (
- [ L"sm-credentials" ],
- Getopt.String (
- s_"SELECTOR",
- fun s ->
- sm_credentials := Some (Subscription_manager.parse_credentials_selector s)
- ),
- s_"Credentials for subscription-manager"
- ),
- Some "SELECTOR", "Set the credentials for C<subscription-manager>.\n\nSee L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of\nthe C<SELECTOR> field.", false;
]
and customize_read_from_file filename =
let forbidden_commands = [
diff --git a/common/mlcustomize/customize_cmdline.mli b/common/mlcustomize/customize_cmdline.mli
index cc32f3af4..baacda9d3 100644
--- a/common/mlcustomize/customize_cmdline.mli
+++ b/common/mlcustomize/customize_cmdline.mli
@@ -77,14 +77,6 @@ and op = [
(* --run-command 'CMD+ARGS' *)
| `Scrub of string
(* --scrub FILE *)
- | `SMAttach of Subscription_manager.sm_pool
- (* --sm-attach SELECTOR *)
- | `SMRegister
- (* --sm-register *)
- | `SMRemove
- (* --sm-remove *)
- | `SMUnregister
- (* --sm-unregister *)
| `SSHInject of string * Ssh_key.ssh_key_selector
(* --ssh-inject USER[:SELECTOR] *)
| `TarIn of string * string
@@ -115,8 +107,6 @@ and flags = {
(* --no-selinux-relabel *)
selinux_relabel_ignored : bool;
(* --selinux-relabel *)
- sm_credentials : Subscription_manager.sm_credentials option;
- (* --sm-credentials SELECTOR *)
}
type argspec = Getopt.keys * Getopt.spec * Getopt.doc
diff --git a/common/mlcustomize/customize_run.ml b/common/mlcustomize/customize_run.ml
index 64afd3ab5..1baf0f3cf 100644
--- a/common/mlcustomize/customize_run.ml
+++ b/common/mlcustomize/customize_run.ml
@@ -279,43 +279,6 @@ let run (g : G.guestfs) root (ops : ops) =
message (f_"Scrubbing: %s") path;
g#scrub_file path
- | `SMAttach pool ->
- (match pool with
- | Subscription_manager.PoolAuto ->
- message (f_"Attaching to compatible subscriptions");
- let cmd = "subscription-manager attach --auto" in
- do_run ~display:cmd ~warn_failed_no_network:true cmd
- | Subscription_manager.PoolId id ->
- message (f_"Attaching to the pool %s") id;
- let cmd = sprintf "subscription-manager attach --pool=%s" (quote id) in
- do_run ~display:cmd ~warn_failed_no_network:true cmd
- )
-
- | `SMRegister ->
- message (f_"Registering with subscription-manager");
- let creds =
- match ops.flags.sm_credentials with
- | None ->
- error (f_"subscription-manager credentials required for \
- --sm-register")
- | Some c -> c in
- let cmd = sprintf "subscription-manager register \
- --username=%s --password=%s"
- (quote creds.Subscription_manager.sm_username)
- (quote creds.Subscription_manager.sm_password) in
- do_run ~display:"subscription-manager register"
- ~warn_failed_no_network:true cmd
-
- | `SMRemove ->
- message (f_"Removing all the subscriptions");
- let cmd = "subscription-manager remove --all" in
- do_run ~display:cmd ~warn_failed_no_network:true cmd
-
- | `SMUnregister ->
- message (f_"Unregistering with subscription-manager");
- let cmd = "subscription-manager unregister" in
- do_run ~display:cmd ~warn_failed_no_network:true cmd
-
| `SSHInject (user, selector) ->
if unix_like (g#inspect_get_type root) then (
message (f_"SSH key inject: %s") user;
diff --git a/common/mlcustomize/subscription_manager.ml b/common/mlcustomize/subscription_manager.ml
deleted file mode 100644
index 104602462..000000000
--- a/common/mlcustomize/subscription_manager.ml
+++ /dev/null
@@ -1,54 +0,0 @@
-(* virt-customize
- * Copyright (C) 2015 Red Hat Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *)
-
-open Std_utils
-open Tools_utils
-open Common_gettext.Gettext
-
-type sm_credentials = {
- sm_username : string;
- sm_password : string;
-}
-
-type sm_pool =
-| PoolAuto
-| PoolId of string
-
-let rec parse_credentials_selector arg =
- parse_credentials_selector_list arg (String.nsplit ":" arg)
-
-and parse_credentials_selector_list orig_arg = function
- | [ username; "password"; password ] ->
- { sm_username = username; sm_password = password }
- | [ username; "file"; filename ] ->
- { sm_username = username; sm_password = read_first_line_from_file filename }
- | _ ->
- error (f_"invalid sm-credentials selector %s; see the man page") orig_arg
-
-let rec parse_pool_selector arg =
- parse_pool_selector_list arg (String.nsplit ":" arg)
-
-and parse_pool_selector_list orig_arg = function
- | [ "auto" ] ->
- PoolAuto
- | [ "pool"; pool ] ->
- PoolId pool
- | [ "file"; filename ] ->
- PoolId (read_first_line_from_file filename)
- | _ ->
- error (f_"invalid sm-attach selector %s; see the man page") orig_arg
diff --git a/common/mlcustomize/subscription_manager.mli b/common/mlcustomize/subscription_manager.mli
deleted file mode 100644
index bb6b92014..000000000
--- a/common/mlcustomize/subscription_manager.mli
+++ /dev/null
@@ -1,34 +0,0 @@
-(* virt-customize
- * Copyright (C) 2015 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.
- *)
-
-type sm_credentials = {
- sm_username : string;
- sm_password : string;
-}
-
-type sm_pool =
-| PoolAuto (** Automatic entitlements. *)
-| PoolId of string (** Specific pool. *)
-
-val parse_credentials_selector : string -> sm_credentials
-(** Parse the selector field in --sm-credentials. Exits if the format
- is not valid. *)
-
-val parse_pool_selector : string -> sm_pool
-(** Parse the selector field in --sm-attach. Exits if the format
- is not valid. *)
diff --git a/common/mlcustomize/v2v-customize-options.pod b/common/mlcustomize/v2v-customize-options.pod
index 0974f4592..f02f05dac 100644
--- a/common/mlcustomize/v2v-customize-options.pod
+++ b/common/mlcustomize/v2v-customize-options.pod
@@ -338,35 +338,6 @@ It cannot delete directories, only regular files.
This is a compatibility option that does nothing.
-=item B<--sm-attach> SELECTOR
-
-Attach to a pool using C<subscription-manager>.
-
-See L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of
-the C<SELECTOR> field.
-
-=item B<--sm-credentials> SELECTOR
-
-Set the credentials for C<subscription-manager>.
-
-See L<virt-builder(1)/SUBSCRIPTION-MANAGER> for the format of
-the C<SELECTOR> field.
-
-=item B<--sm-register>
-
-Register the guest using C<subscription-manager>.
-
-This requires credentials being set using I<--sm-credentials>.
-
-=item B<--sm-remove>
-
-Remove all the subscriptions from the guest using
-C<subscription-manager>.
-
-=item B<--sm-unregister>
-
-Unregister the guest using C<subscription-manager>.
-
=item B<--ssh-inject> USER[:SELECTOR]
Inject an ssh key so the given C<USER> will be able to log in over
diff --git a/common/mlcustomize/v2v-customize-synopsis.pod b/common/mlcustomize/v2v-customize-synopsis.pod
index 7eb0a941c..4c1a1547b 100644
--- a/common/mlcustomize/v2v-customize-synopsis.pod
+++ b/common/mlcustomize/v2v-customize-synopsis.pod
@@ -7,11 +7,9 @@
[--link TARGET:LINK[:LINK..]] [--mkdir DIR] [--move SOURCE:DEST]
[--password USER:SELECTOR] [--root-password SELECTOR]
[--run SCRIPT] [--run-command 'CMD+ARGS'] [--scrub FILE]
- [--sm-attach SELECTOR] [--sm-register] [--sm-remove]
- [--sm-unregister] [--ssh-inject USER[:SELECTOR]]
- [--tar-in TARFILE:REMOTEDIR] [--timezone TIMEZONE] [--touch FILE]
- [--truncate FILE] [--truncate-recursive PATH]
- [--uninstall PKG,PKG..] [--update] [--upload FILE:DEST]
- [--write FILE:CONTENT] [--no-logfile]
+ [--ssh-inject USER[:SELECTOR]] [--tar-in TARFILE:REMOTEDIR]
+ [--timezone TIMEZONE] [--touch FILE] [--truncate FILE]
+ [--truncate-recursive PATH] [--uninstall PKG,PKG..] [--update]
+ [--upload FILE:DEST] [--write FILE:CONTENT] [--no-logfile]
[--password-crypto md5|sha256|sha512] [--no-selinux-relabel]
- [--selinux-relabel] [--sm-credentials SELECTOR]
+ [--selinux-relabel]

View File

@ -0,0 +1,150 @@
From de70086dbe2eb8a6ec023ebbd0c84489a8719ba1 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Tue, 14 Oct 2025 14:16:19 -0400
Subject: [PATCH] pod: Document removal of --sm-* options
Update podcheck.pl to allow for still documenting these
in virt-builder.pod
Signed-off-by: Cole Robinson <crobinso@redhat.com>
(cherry picked from commit 7bad703d724cd976cc3b7760b09af353aab46ff0)
---
builder/virt-builder.pod | 73 +++++++++++++-----------------------
customize/virt-customize.pod | 8 ++++
podcheck.pl | 13 ++++++-
3 files changed, 46 insertions(+), 48 deletions(-)
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index ff0ec250c..f043939ca 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -878,53 +878,6 @@ F<C:\Program Files\Guestfs\Firstboot\log.txt>.
=back
-=head2 SUBSCRIPTION-MANAGER
-
-It is possible to automate the registration and attaching of the
-system using C<subscription-manager>. This is typical on
-Red Hat Enterprise Linux guests. There are few options which ease
-this process, avoid executing commands manually and exposing
-passwords on command line.
-
-I<--sm-register> starts the registration process, and requires
-I<--sm-credentials> to be specified; the format of the C<SELECTOR>
-of I<--sm-credentials> is one of the following formats:
-
-=over 4
-
-=item B<--sm-credentials> USER:file:FILENAME
-
-Read the password for the specified C<USER> from F<FILENAME>.
-
-=item B<--sm-credentials> USER:password:PASSWORD
-
-Use the literal string C<PASSWORD> for the specified C<USER>.
-
-=back
-
-I<--sm-attach> attaches the system to subscriptions; the format
-of its C<SELECTOR> is one of the following:
-
-=over 4
-
-=item B<--sm-attach> auto
-
-C<subscription-manager> attaches to the best-fitting subscriptions
-for the system.
-
-=item B<--sm-attach> file:FILENAME
-
-Read the pool ID from F<FILENAME>.
-
-=item B<--sm-attach> pool:POOL
-
-Use the literal string C<POOL> as pool ID.
-
-=back
-
-I<--sm-remove> removes all the subscriptions from the guest, while
-I<--sm-unregister> completely unregister the system.
-
=head2 INSTALLATION PROCESS
When you invoke virt-builder, installation proceeds as follows:
@@ -1764,6 +1717,32 @@ them, which is normal and harmless.
=back
+=head2 DEPRECATED OPTIONS
+
+In version 1.56 the subscription-manager options were removed.
+
+=over 4
+
+=item B<--sm-credentials>
+
+=item B<--sm-register>
+
+Use --run='subscription-manager register --username=USER --password=PASS'
+
+=item B<--sm-unregister>
+
+Use --run='subscription-manager unregister'
+
+=item B<--sm-attach>
+
+Use --run='subscription-manager attach ...'
+
+=item B<--sm-remove>
+
+Use --run='subscription-manager remove --all'
+
+=back
+
=head1 MACHINE READABLE OUTPUT
The I<--machine-readable> option can be used to make the output more
diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod
index fb3d65665..9fee64ebc 100644
--- a/customize/virt-customize.pod
+++ b/customize/virt-customize.pod
@@ -248,6 +248,14 @@ existing ones.
For further details, see L<virt-builder(1)/SELINUX>.
+=head1 DEPRECATED OPTIONS
+
+In version 1.56 the subscription-manager options were removed:
+B<--sm-credentials>, B<--sm-register>, B<--sm-unregister>,
+B<--sm-attach>, B<--sm-remove>
+
+For further details, see L<virt-builder(1)/DEPRECATED OPTIONS>.
+
=head1 EXIT STATUS
This program returns 0 on success, or 1 if there was an error.
diff --git a/podcheck.pl b/podcheck.pl
index 795fe0e9b..047bbf8da 100755
--- a/podcheck.pl
+++ b/podcheck.pl
@@ -203,7 +203,18 @@ my $pod_options_checked = 0;
my %pod_options = ();
$pod_options{$_} = 1 foreach ( $content =~ /^=item.*B<(-[-\w]+)(?:=.*)?>/gm );
-foreach (sort keys %pod_options) {
+
+my %pod_option_exists = ();
+$pod_option_exists{$_} = 1 foreach keys %pod_options;
+
+# Removed from the tool but we still document them
+delete $pod_option_exists{"--sm-credentials"};
+delete $pod_option_exists{"--sm-register"};
+delete $pod_option_exists{"--sm-unregister"};
+delete $pod_option_exists{"--sm-remove"};
+delete $pod_option_exists{"--sm-attach"};
+
+foreach (sort keys %pod_option_exists) {
unless ($ignore{$_}) {
$pod_options_checked++;
unless (exists $tool_option_exists{$_}) {

View File

@ -0,0 +1,31 @@
From 269302e1a500d3cba94194faa258f6b47fef88fb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 4 Nov 2025 13:04:12 +0000
Subject: [PATCH] test-data/phony-guests: Increase size of Windows image
For testing I tried to upload a very large Windows registry to the
phony Windows image. However because of the 256M limit on the size of
the second partition (and NTFS overhead?) this was not possible.
There's no real penalty to increasing the size of this image since
it's just virtual space, so increase the virtual size to 2G (256M/1.7G
split).
(cherry picked from commit a39ae0b898825970549876738bd465f6a110de7c)
---
test-data/phony-guests/make-windows-img.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test-data/phony-guests/make-windows-img.sh b/test-data/phony-guests/make-windows-img.sh
index 0ec6b4851..e72013c3d 100755
--- a/test-data/phony-guests/make-windows-img.sh
+++ b/test-data/phony-guests/make-windows-img.sh
@@ -37,7 +37,7 @@ fi
# Create a disk image.
guestfish <<EOF
-sparse windows.img-t 512M
+sparse windows.img-t 2G
run
# Format the disk.

View File

@ -0,0 +1,72 @@
From 63df59b34bb0a19f6b1e2821250106691d1945a9 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 3 Nov 2025 15:26:19 +0000
Subject: [PATCH] inspector: Add new <class> field to output of virt-inspector
Rebase common submodule to pick up:
Richard W.M. Jones (1):
structs/structs-print.c: Update this generated file
Fixes: https://issues.redhat.com/browse/RHEL-125955
(cherry picked from commit 53e59d0189dc71d78559478c4924f1a1a994c455)
---
common | 2 +-
inspector/inspector.c | 2 ++
inspector/virt-inspector.rng | 1 +
m4/guestfs-libraries.m4 | 3 ++-
4 files changed, 6 insertions(+), 2 deletions(-)
Submodule common 90399dd18..b54ba2031:
diff --git a/common/structs/structs-print.c b/common/structs/structs-print.c
index bfe007cde..8c376b0ee 100644
--- a/common/structs/structs-print.c
+++ b/common/structs/structs-print.c
@@ -63,7 +63,7 @@ guestfs_int_print_application2_indent (struct guestfs_application2 *application2
fprintf (dest, "%sapp2_source_package: %s%s", indent, application2->app2_source_package, linesep);
fprintf (dest, "%sapp2_summary: %s%s", indent, application2->app2_summary, linesep);
fprintf (dest, "%sapp2_description: %s%s", indent, application2->app2_description, linesep);
- fprintf (dest, "%sapp2_spare1: %s%s", indent, application2->app2_spare1, linesep);
+ fprintf (dest, "%sapp2_class: %s%s", indent, application2->app2_class, linesep);
fprintf (dest, "%sapp2_spare2: %s%s", indent, application2->app2_spare2, linesep);
fprintf (dest, "%sapp2_spare3: %s%s", indent, application2->app2_spare3, linesep);
fprintf (dest, "%sapp2_spare4: %s%s", indent, application2->app2_spare4, linesep);
diff --git a/inspector/inspector.c b/inspector/inspector.c
index 1177f44a4..cccc209d0 100644
--- a/inspector/inspector.c
+++ b/inspector/inspector.c
@@ -697,6 +697,8 @@ output_applications (xmlTextWriterPtr xo, char *root)
single_element ("summary", apps->val[i].app2_summary);
if (apps->val[i].app2_description && apps->val[i].app2_description[0])
single_element ("description", apps->val[i].app2_description);
+ if (apps->val[i].app2_class && apps->val[i].app2_class[0])
+ single_element ("class", apps->val[i].app2_class);
} end_element ();
}
} end_element ();
diff --git a/inspector/virt-inspector.rng b/inspector/virt-inspector.rng
index 29c5798e1..e30686d4f 100644
--- a/inspector/virt-inspector.rng
+++ b/inspector/virt-inspector.rng
@@ -212,6 +212,7 @@
<optional><element name="source_package"><text/></element></optional>
<optional><element name="summary"><text/></element></optional>
<optional><element name="description"><text/></element></optional>
+ <optional><element name="class"><text/></element></optional>
</element>
</zeroOrMore>
</element>
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 82e62d54f..4ca86161c 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -20,7 +20,8 @@ dnl Any C libraries required by the libguestfs C library (not the daemon).
dnl Of course we need libguestfs.
dnl
dnl We need libguestfs 1.57.1 for guestfs_setfiles.
-PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.57.1])
+dnl We need libguestfs 1.57.6 for guestfs_inspect_get_applications2 app2_class.
+PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.57.6])
printf "libguestfs version is "; $PKG_CONFIG --modversion libguestfs
dnl Test if it's GNU or XSI strerror_r.

View File

@ -0,0 +1,52 @@
From c715ed2a3b82ce6cfcd44fbb8a29476621ebe049 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 3 Nov 2025 15:56:56 +0000
Subject: [PATCH] inspector: Add <windows_group_policy/> is Windows GPOs
detected in guest
Fixes: https://issues.redhat.com/browse/RHEL-125955
(cherry picked from commit d56129cfccedd26739ee5b813060e7547d977c53)
---
inspector/inspector.c | 3 +++
inspector/virt-inspector.rng | 1 +
m4/guestfs-libraries.m4 | 1 +
3 files changed, 5 insertions(+)
diff --git a/inspector/inspector.c b/inspector/inspector.c
index cccc209d0..6b5d50157 100644
--- a/inspector/inspector.c
+++ b/inspector/inspector.c
@@ -439,6 +439,9 @@ output_root (xmlTextWriterPtr xo, char *root)
if (str)
single_element ("windows_current_control_set", str);
free (str);
+ i = guestfs_inspect_get_windows_group_policy (g, root);
+ if (i > 0)
+ empty_element ("windows_group_policy");
guestfs_pop_error_handler (g);
str = guestfs_inspect_get_hostname (g, root);
diff --git a/inspector/virt-inspector.rng b/inspector/virt-inspector.rng
index e30686d4f..90f74cf78 100644
--- a/inspector/virt-inspector.rng
+++ b/inspector/virt-inspector.rng
@@ -35,6 +35,7 @@
<element name="minor_version"><text/></element>
<optional><element name="windows_systemroot"><text/></element></optional>
<optional><element name="windows_current_control_set"><text/></element></optional>
+ <optional><element name="windows_group_policy"><empty/></element></optional>
<optional><ref name="ospackageformat"/></optional>
<optional><ref name="ospackagemanagement"/></optional>
<optional><element name="hostname"><text/></element></optional>
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 4ca86161c..02f2281f8 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -21,6 +21,7 @@ dnl Of course we need libguestfs.
dnl
dnl We need libguestfs 1.57.1 for guestfs_setfiles.
dnl We need libguestfs 1.57.6 for guestfs_inspect_get_applications2 app2_class.
+dnl We need libguestfs 1.57.6 for guestfs_inspect_get_windows_group_policy
PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.57.6])
printf "libguestfs version is "; $PKG_CONFIG --modversion libguestfs

View File

@ -0,0 +1,139 @@
From d1ca20bde34a4085f3ec7e3e418d01bc4deb2698 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 26 Jan 2026 15:26:23 +0000
Subject: [PATCH] inspector: For xfs, try to find and print the filesystem
version
RHEL 7.0, 7.1 and (possibly*) 7.2 used XFS version 4. New versions of
RHEL use XFS v5.
Support even for opening version 4 filesystems was removed in RHEL 10
(and will be removed altogether from the Linux kernel in 2030). This
prevents virt-v2v conversions or libguestfs in general from accessing
those filesystems.
Therefore it's a good idea to be able to tell the XFS filesystem
version and print that in virt-inspector output.
The new output will look like:
<filesystems>
<filesystem dev="/dev/sda2">
<type version="5">xfs</type>
<uuid>35904e42-4e3d-40c7-a4ef-213786c18339</uuid>
</filesystem>
To work this requires libguestfs >= 1.59.2 (with guestfs_xfs_info2).
Older versions of libguestfs, or if we cannot tell the version, will
not have the version attribute.
* = The virt-builder rhel-7.2 image definitely uses XFS v4, but it may
have been built from an early (pre-)release of 7.2. Later RHEL 7.2
seems to use XFS v5.
Fixes: https://issues.redhat.com/browse/RHEL-144074
(cherry picked from commit bb210ca4330bc307d972201faf713d4c3c49fc6a)
---
inspector/inspector.c | 54 ++++++++++++++++++++++++++++++++----
inspector/virt-inspector.rng | 9 +++++-
2 files changed, 56 insertions(+), 7 deletions(-)
diff --git a/inspector/inspector.c b/inspector/inspector.c
index 6b5d50157..fc6b9f0d0 100644
--- a/inspector/inspector.c
+++ b/inspector/inspector.c
@@ -569,6 +569,42 @@ output_mountpoints (xmlTextWriterPtr xo, char *root)
} end_element ();
}
+static const char *
+get_filesystem_version (const char *dev, const char *fs_type)
+{
+ const char *version = NULL;
+
+#ifdef GUESTFS_HAVE_XFS_INFO2
+ /* For type=xfs, try to guess the filesystem version. */
+ if (STREQ (fs_type, "xfs")) {
+ CLEANUP_FREE_STRING_LIST char **hash = NULL;
+ size_t i;
+
+ guestfs_push_error_handler (g, NULL, NULL);
+
+ hash = guestfs_xfs_info2 (g, dev);
+ if (hash) {
+ for (i = 0; hash[i] != NULL; i += 2) {
+ if (STREQ (hash[i], "meta-data.crc")) {
+ if (STREQ (hash[i+1], "0"))
+ version = "4";
+ else if (STREQ (hash[i+1], "1"))
+ version = "5";
+ break;
+ }
+ /* If new XFS versions are added in future then we can test
+ * for new fields here ...
+ */
+ }
+ }
+
+ guestfs_pop_error_handler (g);
+ }
+#endif /* GUESTFS_HAVE_XFS_INFO2 */
+
+ return version;
+}
+
static void
output_filesystems (xmlTextWriterPtr xo, char *root)
{
@@ -586,19 +622,25 @@ output_filesystems (xmlTextWriterPtr xo, char *root)
start_element ("filesystems") {
for (i = 0; filesystems[i] != NULL; ++i) {
- str = guestfs_canonical_device_name (g, filesystems[i]);
- if (!str)
+ CLEANUP_FREE char *dev =
+ guestfs_canonical_device_name (g, filesystems[i]);
+ if (!dev)
exit (EXIT_FAILURE);
start_element ("filesystem") {
- attribute ("dev", str);
- free (str);
+ attribute ("dev", dev);
guestfs_push_error_handler (g, NULL, NULL);
str = guestfs_vfs_type (g, filesystems[i]);
- if (str && str[0])
- single_element ("type", str);
+ if (str && str[0]) {
+ const char *version = get_filesystem_version (dev, str);
+ start_element ("type") {
+ if (version)
+ attribute ("version", version);
+ string (str);
+ } end_element ();
+ }
free (str);
str = guestfs_vfs_label (g, filesystems[i]);
diff --git a/inspector/virt-inspector.rng b/inspector/virt-inspector.rng
index 90f74cf78..aeec082ff 100644
--- a/inspector/virt-inspector.rng
+++ b/inspector/virt-inspector.rng
@@ -175,7 +175,14 @@
<element name="filesystem">
<attribute name="dev"><text/></attribute>
<interleave>
- <optional><element name="type"><text/></element></optional>
+ <optional>
+ <element name="type">
+ <optional>
+ <attribute name="version"><text/></attribute>
+ </optional>
+ <text/>
+ </element>
+ </optional>
<optional><element name="label"><text/></element></optional>
<optional><element name="uuid"><text/></element></optional>
</interleave>

View File

@ -0,0 +1,35 @@
From 83d338a7691d6c1ef169fb62011854bb9b450917 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 5 Feb 2026 11:57:33 +0000
Subject: [PATCH] Sort some entries in .gitignore into order
(cherry picked from commit 9d7161da76160b2e5d1f3488b3f0a652554d2077)
---
.gitignore | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
index 94f77ac74..023686435 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,9 +81,9 @@ Makefile.in
/cat/virt-ls
/cat/virt-tail
/config.cache
-/config.log
/config.h
/config.h.in
+/config.log
/config.sh
/config.status
/configure
@@ -112,8 +112,8 @@ Makefile.in
/ocaml-dep.sh
/ocaml-link.sh
/po-docs/*/*.pod
-/podwrapper.pl
/po/*.gmo
+/podwrapper.pl
/resize/.depend
/resize/virt-resize
/run

View File

@ -0,0 +1,35 @@
From 590c1aae4d7baadd21ff862c96d4516f52ae9c32 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 22 Sep 2025 10:58:29 +0100
Subject: [PATCH] build: Add $(NULL) as a convenient list terminator
When building lists of things in Makefiles it's convenient to have a
list terminator to avoid hanging backslash problems. eg:
EXTRA_DIST = \
thing1 \
thing2 \
$(NULL)
Cherry picked from virt-v2v commit 09b86c07bf19beba9ccb8fcca0ebfae34dd56406
(cherry picked from commit dad8c0d3803dcbc91e22ca35c630d9e8a01df81b)
---
common-rules.mk | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/common-rules.mk b/common-rules.mk
index 4df1e33f1..7a116c827 100644
--- a/common-rules.mk
+++ b/common-rules.mk
@@ -20,6 +20,10 @@
-include $(top_builddir)/localenv
+# Convenient way to terminate lists in Makefiles, so that we avoid
+# problems with dangling backslashes.
+NULL =
+
# Files that should universally be removed by 'make clean'. Note if
# there is any case in any subdirectory where a file should not be
# removed by 'make clean', it should not be listed here!

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,473 @@
From 52a921e1276748f9de7115078fd2999e750299c0 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 5 Feb 2026 13:17:38 +0000
Subject: [PATCH] filesystems: Optionally display filesystem version
Unlike the recent change to virt-inspector (commit bb210ca433
("inspector: For xfs, try to find and print the filesystem version"))
this does not require the ability to mount the XFS v4 filesystem so it
will work on RHEL 10.
$ virt-filesystems -a rhel-7.0.img --long --fs-version
Name Type VFS Label Size Parent FSVersion
/dev/sda1 filesystem ext4 - 510873600 - -
/dev/sda3 filesystem xfs - 4820303872 - 4
$ virt-filesystems -a rhel-7.3.img --long --fs-version
Name Type VFS Label Size Parent FSVersion
/dev/sda1 filesystem ext4 - 510873600 - -
/dev/sda3 filesystem xfs - 4820303872 - 5
Fixes: https://issues.redhat.com/browse/RHEL-144074
(cherry picked from commit fc61c9439d84fdaab71e1628eb5b95f18ff40ce1)
---
.gitignore | 1 +
filesystems/Makefile.am | 6 +++-
filesystems/filesystems.c | 46 ++++++++++++++++++------
filesystems/utils.c | 60 ++++++++++++++++++++++++++++++++
filesystems/utils.h | 30 ++++++++++++++++
filesystems/virt-filesystems.pod | 12 ++++++-
inspector/Makefile.am | 6 +++-
inspector/inspector.c | 39 ++-------------------
8 files changed, 150 insertions(+), 50 deletions(-)
create mode 100644 filesystems/utils.c
create mode 100644 filesystems/utils.h
diff --git a/.gitignore b/.gitignore
index ed850a20f..0b26da37b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@
stamp-*.pod
.deps
+.dirstamp
.libs
Makefile
Makefile.in
diff --git a/filesystems/Makefile.am b/filesystems/Makefile.am
index 17e3b9c6f..625592ff3 100644
--- a/filesystems/Makefile.am
+++ b/filesystems/Makefile.am
@@ -25,7 +25,11 @@ EXTRA_DIST = \
bin_PROGRAMS = virt-filesystems
-virt_filesystems_SOURCES = filesystems.c
+virt_filesystems_SOURCES = \
+ filesystems.c \
+ utils.c \
+ utils.h \
+ $(NULL)
virt_filesystems_CPPFLAGS = \
-DGUESTFS_NO_DEPRECATED=1 \
diff --git a/filesystems/filesystems.c b/filesystems/filesystems.c
index ecaeb0bb2..e86d92be0 100644
--- a/filesystems/filesystems.c
+++ b/filesystems/filesystems.c
@@ -39,6 +39,7 @@
#include "structs-cleanups.h"
#include "options.h"
#include "display-options.h"
+#include "utils.h"
/* These globals are shared with options.c. */
guestfs_h *g;
@@ -75,7 +76,8 @@ static int output = 0;
#define COLUMN_SIZE 32 /* bytes, or human-readable if -h */
#define COLUMN_PARENTS 64
#define COLUMN_UUID 128 /* if --uuid */
-#define NR_COLUMNS 8
+#define COLUMN_FS_VERSION 256 /* if --fs-version */
+#define NR_COLUMNS 9
static int columns;
static void do_output_title (void);
@@ -111,6 +113,8 @@ usage (int status)
" --extra Display swap and data filesystems\n"
" --filesystems Display mountable filesystems\n"
" --format[=raw|..] Force disk format for -a option\n"
+ " --fs-version|--fs-versions\n"
+ " Add filesystem version to --long output\n"
" -h|--human-readable Human-readable sizes in --long output\n"
" --help Display brief help\n"
" --keys-from-stdin Read passphrases from stdin\n"
@@ -157,6 +161,8 @@ main (int argc, char *argv[])
{ "extra", 0, 0, 0 },
{ "filesystems", 0, 0, 0 },
{ "format", 2, 0, 0 },
+ { "fs-version", 0, 0, 0 },
+ { "fs-versions", 0, 0, 0 },
{ "help", 0, 0, HELP_OPTION },
{ "human-readable", 0, 0, 'h' },
{ "keys-from-stdin", 0, 0, 0 },
@@ -191,6 +197,7 @@ main (int argc, char *argv[])
int no_title = 0; /* --no-title */
int long_mode = 0; /* --long|-l */
int uuid = 0; /* --uuid */
+ int fs_version = 0; /* --fs-version */
int title;
g = guestfs_create ();
@@ -227,6 +234,9 @@ main (int argc, char *argv[])
output |= OUTPUT_FILESYSTEMS_EXTRA;
} else if (STREQ (long_options[option_index].name, "filesystems")) {
output |= OUTPUT_FILESYSTEMS;
+ } else if (STREQ (long_options[option_index].name, "fs-version") ||
+ STREQ (long_options[option_index].name, "fs-versions")) {
+ fs_version = 1;
} else if (STREQ (long_options[option_index].name, "logical-volumes") ||
STREQ (long_options[option_index].name, "logvols") ||
STREQ (long_options[option_index].name, "lvs")) {
@@ -337,6 +347,8 @@ main (int argc, char *argv[])
columns |= COLUMN_MBR;
if (uuid)
columns |= COLUMN_UUID;
+ if (fs_version)
+ columns |= COLUMN_FS_VERSION;
}
/* Display title by default only in long mode. */
@@ -379,7 +391,7 @@ static void do_output_pvs (void);
static void do_output_partitions (void);
static void do_output_blockdevs (void);
-static void write_row (const char *name, const char *type, const char *vfs_type, const char *vfs_label, int mbr_id, int64_t size, char **parents, const char *uuid);
+static void write_row (const char *name, const char *type, const char *vfs_type, const char *vfs_label, int mbr_id, int64_t size, char **parents, const char *uuid, const char *fs_version);
static void write_row_strings (char **strings, size_t len);
static char **no_parents (void);
@@ -410,6 +422,8 @@ do_output_title (void)
headings[len++] = "Parent";
if ((columns & COLUMN_UUID))
headings[len++] = "UUID";
+ if ((columns & COLUMN_FS_VERSION))
+ headings[len++] = "FSVersion";
assert (len <= NR_COLUMNS);
write_row_strings ((char **) headings, len);
@@ -450,13 +464,15 @@ do_output_filesystems (void)
exit (EXIT_FAILURE);
for (i = 0; fses[i] != NULL; i += 2) {
+ const char *fs_type = fses[i+1];
CLEANUP_FREE char *dev = NULL, *vfs_label = NULL, *vfs_uuid = NULL;
+ CLEANUP_FREE char *fs_version = NULL;
CLEANUP_FREE_STRING_LIST char **parents = NULL;
int64_t size = -1;
/* Skip swap and unknown, unless --extra flag was given. */
if (!(output & OUTPUT_FILESYSTEMS_EXTRA) &&
- (STREQ (fses[i+1], "swap") || STREQ (fses[i+1], "unknown")))
+ (STREQ (fs_type, "swap") || STREQ (fs_type, "unknown")))
continue;
dev = guestfs_canonical_device_name (g, fses[i]);
@@ -486,6 +502,12 @@ do_output_filesystems (void)
error (EXIT_FAILURE, errno, "strdup");
}
}
+ if ((columns & COLUMN_FS_VERSION)) {
+ const char *version = get_filesystem_version (g, fses[i], fs_type);
+ fs_version = strdup (version ? version : "");
+ if (fs_version == NULL)
+ error (EXIT_FAILURE, errno, "strdup");
+ }
if ((columns & COLUMN_SIZE)) {
CLEANUP_FREE char *device = guestfs_mountable_device (g, fses[i]);
CLEANUP_FREE char *subvolume = NULL;
@@ -533,7 +555,7 @@ do_output_filesystems (void)
parents = no_parents ();
write_row (dev, "filesystem",
- fses[i+1], vfs_label, -1, size, parents, vfs_uuid);
+ fs_type, vfs_label, -1, size, parents, vfs_uuid, fs_version);
}
}
@@ -573,7 +595,7 @@ do_output_lvs (void)
}
write_row (lvs[i], "lv",
- NULL, NULL, -1, size, (char **) parents, uuid);
+ NULL, NULL, -1, size, (char **) parents, uuid, NULL);
}
}
@@ -601,7 +623,8 @@ do_output_vgs (void)
parents = parents_of_vg (vgs->val[i].vg_name);
write_row (name, "vg",
- NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, parents, uuid);
+ NULL, NULL, -1, (int64_t) vgs->val[i].vg_size, parents, uuid,
+ NULL);
}
}
@@ -649,7 +672,7 @@ do_output_pvs (void)
uuid[32] = '\0';
write_row (dev, "pv",
NULL, NULL, -1, (int64_t) pvs->val[i].pv_size,
- (char **) parents, uuid);
+ (char **) parents, uuid, NULL);
}
}
@@ -715,7 +738,7 @@ do_output_partitions (void)
}
write_row (dev, "partition",
- NULL, NULL, mbr_id, size, (char **) parents, NULL);
+ NULL, NULL, mbr_id, size, (char **) parents, NULL, NULL);
}
}
@@ -749,7 +772,7 @@ do_output_blockdevs (void)
parents = no_parents ();
write_row (dev, "device",
- NULL, NULL, -1, size, parents, NULL);
+ NULL, NULL, -1, size, parents, NULL, NULL);
}
}
@@ -882,7 +905,8 @@ parents_of_vg (char *vg)
static void
write_row (const char *name, const char *type,
const char *vfs_type, const char *vfs_label, int mbr_id,
- int64_t size, char **parents, const char *uuid)
+ int64_t size, char **parents, const char *uuid,
+ const char *fs_version)
{
const char *strings[NR_COLUMNS];
CLEANUP_FREE char *parents_str = NULL;
@@ -930,6 +954,8 @@ write_row (const char *name, const char *type,
}
if ((columns & COLUMN_UUID))
strings[len++] = uuid;
+ if ((columns & COLUMN_FS_VERSION))
+ strings[len++] = fs_version;
assert (len <= NR_COLUMNS);
write_row_strings ((char **) strings, len);
diff --git a/filesystems/utils.c b/filesystems/utils.c
new file mode 100644
index 000000000..9de32f1bd
--- /dev/null
+++ b/filesystems/utils.c
@@ -0,0 +1,60 @@
+/* Utility function used by virt-filesystems and virrt-inspector
+ * Copyright (C) 2026 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.
+ */
+
+#include <config.h>
+
+#include "guestfs.h"
+
+#include "guestfs-utils.h"
+#include "utils.h"
+
+const char *
+get_filesystem_version (guestfs_h *g, const char *dev, const char *fs_type)
+{
+ const char *version = NULL;
+
+#ifdef GUESTFS_HAVE_XFS_INFO2
+ /* For type=xfs, try to guess the filesystem version. */
+ if (STREQ (fs_type, "xfs")) {
+ CLEANUP_FREE_STRING_LIST char **hash = NULL;
+ size_t i;
+
+ guestfs_push_error_handler (g, NULL, NULL);
+
+ hash = guestfs_xfs_info2 (g, dev);
+ if (hash) {
+ for (i = 0; hash[i] != NULL; i += 2) {
+ if (STREQ (hash[i], "meta-data.crc")) {
+ if (STREQ (hash[i+1], "0"))
+ version = "4";
+ else if (STREQ (hash[i+1], "1"))
+ version = "5";
+ break;
+ }
+ /* If new XFS versions are added in future then we can test
+ * for new fields here ...
+ */
+ }
+ }
+
+ guestfs_pop_error_handler (g);
+ }
+#endif /* GUESTFS_HAVE_XFS_INFO2 */
+
+ return version;
+}
diff --git a/filesystems/utils.h b/filesystems/utils.h
new file mode 100644
index 000000000..284f8e1ac
--- /dev/null
+++ b/filesystems/utils.h
@@ -0,0 +1,30 @@
+/* Utility function used by virt-filesystems and virrt-inspector
+ * Copyright (C) 2026 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.
+ */
+
+#ifndef GUESTFS_FILESYSTEMS_UTILS_H
+#define GUESTFS_FILESYSTEMS_UTILS_H
+
+#include "guestfs.h"
+
+/* For XFS, return the filesystem version (eg. "4" or "5"). This may
+ * return NULL if no filesystem version is known.
+ */
+const char *get_filesystem_version (guestfs_h *g,
+ const char *dev, const char *fs_type);
+
+#endif /* GUESTFS_FILESYSTEMS_UTILS_H */
diff --git a/filesystems/virt-filesystems.pod b/filesystems/virt-filesystems.pod
index 7955d6a84..c72ae3cf7 100644
--- a/filesystems/virt-filesystems.pod
+++ b/filesystems/virt-filesystems.pod
@@ -197,6 +197,14 @@ If you have untrusted raw-format guest disk images, you should use
this option to specify the disk format. This avoids a possible
security problem with malicious guests (CVE-2010-3851).
+=item B<--fs-version>
+
+=item B<--fs-versions>
+
+In I<--long> mode, display the filesystem version. Currently this
+only has any effect for XFS, displaying either C<4> (for XFS v4) or
+C<5> (for XFS v5). XFS v4 support will be removed from Linux in 2030.
+
=item B<-h>
=item B<--human-readable>
@@ -221,7 +229,9 @@ external programs.
Use I<-h> if you want sizes to be displayed in human-readable format.
The default is to show raw numbers of I<bytes>.
-Use I<--uuid> to display UUIDs too.
+Use I<--fs-version> to display filesystem versions.
+
+Use I<--uuid> to display UUIDs.
=item B<--lvs>
diff --git a/inspector/Makefile.am b/inspector/Makefile.am
index 04c608f44..637a10415 100644
--- a/inspector/Makefile.am
+++ b/inspector/Makefile.am
@@ -48,7 +48,10 @@ dist_doc_DATA = \
bin_PROGRAMS = virt-inspector
virt_inspector_SOURCES = \
- inspector.c
+ ../filesystems/utils.c \
+ ../filesystems/utils.h \
+ inspector.c \
+ $(NULL)
virt_inspector_CPPFLAGS = \
-DGUESTFS_NO_DEPRECATED=1 \
@@ -56,6 +59,7 @@ virt_inspector_CPPFLAGS = \
-I$(top_srcdir)/common/utils -I$(top_builddir)/common/utils \
-I$(top_srcdir)/common/structs -I$(top_builddir)/common/structs \
-I$(top_srcdir)/lib -I$(top_builddir)/lib \
+ -I$(top_srcdir)/filesystems -I$(top_builddir)/filesystems \
-I$(top_srcdir)/include \
-I$(top_srcdir)/common/options -I$(top_builddir)/common/options \
-I$(top_srcdir)/fish \
diff --git a/inspector/inspector.c b/inspector/inspector.c
index fc6b9f0d0..be34e8794 100644
--- a/inspector/inspector.c
+++ b/inspector/inspector.c
@@ -44,6 +44,7 @@
#include "options.h"
#include "display-options.h"
#include "libxml2-writer-macros.h"
+#include "utils.h"
/* Currently open libguestfs handle. */
guestfs_h *g;
@@ -569,42 +570,6 @@ output_mountpoints (xmlTextWriterPtr xo, char *root)
} end_element ();
}
-static const char *
-get_filesystem_version (const char *dev, const char *fs_type)
-{
- const char *version = NULL;
-
-#ifdef GUESTFS_HAVE_XFS_INFO2
- /* For type=xfs, try to guess the filesystem version. */
- if (STREQ (fs_type, "xfs")) {
- CLEANUP_FREE_STRING_LIST char **hash = NULL;
- size_t i;
-
- guestfs_push_error_handler (g, NULL, NULL);
-
- hash = guestfs_xfs_info2 (g, dev);
- if (hash) {
- for (i = 0; hash[i] != NULL; i += 2) {
- if (STREQ (hash[i], "meta-data.crc")) {
- if (STREQ (hash[i+1], "0"))
- version = "4";
- else if (STREQ (hash[i+1], "1"))
- version = "5";
- break;
- }
- /* If new XFS versions are added in future then we can test
- * for new fields here ...
- */
- }
- }
-
- guestfs_pop_error_handler (g);
- }
-#endif /* GUESTFS_HAVE_XFS_INFO2 */
-
- return version;
-}
-
static void
output_filesystems (xmlTextWriterPtr xo, char *root)
{
@@ -634,7 +599,7 @@ output_filesystems (xmlTextWriterPtr xo, char *root)
str = guestfs_vfs_type (g, filesystems[i]);
if (str && str[0]) {
- const char *version = get_filesystem_version (dev, str);
+ const char *version = get_filesystem_version (g, dev, str);
start_element ("type") {
if (version)
attribute ("version", version);

View File

@ -0,0 +1,28 @@
From 3051cfbed63f8f8865b4a3374a474031dc916faa Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 10 Dec 2025 13:47:00 +0000
Subject: [PATCH] Update common submodule
Pull in this change:
Richard W.M. Jones (1):
mlcustomize/firstboot.ml: Print %USERNAME% and %USERDOMAIN%
(cherry picked from commit 7ee462f9f9c2235b2d3dacbf3cd1006060108635)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common b54ba2031..d03dd8547:
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index 360c33d67..c1738e749 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -295,6 +295,7 @@ exit /b
:main
echo starting firstboot service
+echo effective user: %USERNAME% domain: %USERDOMAIN%
if not exist "%%scripts_done%%" (
mkdir "%%scripts_done%%"

View File

@ -0,0 +1,25 @@
From f0e429ec0eadf74594fd3202f77b7191963df771 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 10 Dec 2025 14:06:10 +0000
Subject: [PATCH] Update common submodule
Fixes: commit 7ee462f9f9c2235b2d3dacbf3cd1006060108635
(cherry picked from commit 6436529d116dd415b26841d7b4bcee7564a97b0f)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common d03dd8547..cf663a835:
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index c1738e749..f29884c88 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -295,7 +295,7 @@ exit /b
:main
echo starting firstboot service
-echo effective user: %USERNAME% domain: %USERDOMAIN%
+echo effective user: %%USERNAME%% domain: %%USERDOMAIN%%
if not exist "%%scripts_done%%" (
mkdir "%%scripts_done%%"

View File

@ -0,0 +1,638 @@
From 001cb3dddd4ddc218d02558a46070545bbca3c98 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 16 Mar 2026 09:38:37 +0000
Subject: [PATCH] Update common submodule
Cole Robinson (2):
virtio-win: Install blnsvr.exe to C:\Windows\Drivers\VirtIO
build: mark some ocaml commands with $(AM_V_GEN)
Richard W.M. Jones (7):
mlpcre: Add optional PCRE_ANCHORED flag when compiling expressions
mlstdutils: Export List.assoc_opt
mlcustomize/firstboot.ml: Be more careful about quoting
mlcustomize: Create a sentinel file when firstboot completes
mlutils/c_utils-c.c: Throw Unix_error on failure
Use caml_unix_error instead of unix_error
mlutils/unix_utils.ml: statvfs_is_network_filesystem should not be noalloc
grass-lu (1):
Add support for Kylin, NeoKylin and Anolis Linux
shivanayak (5):
common: fix FILE stream leak in worker_thread on guestfs_create failure (#27)
options: fix memory leak in read_key on getline failure (#30)
edit: check WIFEXITED before WEXITSTATUS in edit_file_editor and edit_file_perl (#31)
mlutils: fix pattern leak in mkdtemp wrapper on failure
qemuopts: check for write errors in qemuopts_to_channel and qemuopts_to_config_channel (#33)
(cherry picked from commit a735b6b45de2afaddd4d4287cd666a5afc9ec964)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common cf663a835..c8e64b3ff:
diff --git a/common/edit/file-edit.c b/common/edit/file-edit.c
index ef56ed13d..a10d61c99 100644
--- a/common/edit/file-edit.c
+++ b/common/edit/file-edit.c
@@ -119,7 +119,7 @@ edit_file_editor (guestfs_h *g, const char *filename, const char *editor,
fprintf (stderr, "%s\n", cmd);
r = system (cmd);
- if (r == -1 || WEXITSTATUS (r) != 0) {
+ if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0) {
perror (cmd);
return -1;
}
@@ -194,7 +194,7 @@ edit_file_perl (guestfs_h *g, const char *filename, const char *perl_expr,
fprintf (stderr, "%s\n", cmd);
r = system (cmd);
- if (r == -1 || WEXITSTATUS (r) != 0)
+ if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0)
return -1;
if (rename (outfile, tmpfilename) == -1) {
diff --git a/common/mlcustomize/Makefile.am b/common/mlcustomize/Makefile.am
index 351524c80..3bdff2a63 100644
--- a/common/mlcustomize/Makefile.am
+++ b/common/mlcustomize/Makefile.am
@@ -142,7 +142,7 @@ endif
libmlcustomize_a_DEPENDENCIES = $(OBJECTS)
$(MLCUSTOMIZE_CMA): $(OBJECTS) libmlcustomize.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlcustomize_a_OBJECTS) -o mlcustomize
# Tests.
diff --git a/common/mlcustomize/crypt-c.c b/common/mlcustomize/crypt-c.c
index e358018cd..e1bc740d1 100644
--- a/common/mlcustomize/crypt-c.c
+++ b/common/mlcustomize/crypt-c.c
@@ -47,7 +47,7 @@ virt_customize_crypt (value keyv, value saltv)
*/
r = crypt (String_val (keyv), String_val (saltv));
if (r == NULL)
- unix_error (errno, (char *) "crypt", Nothing);
+ caml_unix_error (errno, (char *) "crypt", Nothing);
rv = caml_copy_string (r);
CAMLreturn (rv);
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index f29884c88..543e98fb1 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -151,7 +151,7 @@ WantedBy=%s
and install_sysvinit_service g root distro major =
match distro with
| "fedora"|"rhel"|"centos"|"scientificlinux"|"oraclelinux"|"rocky"|
- "redhat-based"|"openeuler" ->
+ "redhat-based"|"openeuler"|"kylin"|"neokylin"|"anolis" ->
install_sysvinit_redhat g
| "opensuse"|"sles"|"suse-based" ->
install_sysvinit_suse g
@@ -271,6 +271,9 @@ module Windows = struct
(* Create a directory for firstboot scripts in the guest. *)
g#mkdir_p (firstboot_dir // "scripts");
+ (* Remove the sentinel file if it exists from a previous run. *)
+ g#rm_f (firstboot_dir // "complete");
+
(* Copy pvvxsvc or rhsrvany to the guest. *)
g#upload (virt_tools_data_dir () // srvany) (firstboot_dir // srvany);
@@ -284,11 +287,11 @@ module Windows = struct
let firstboot_script = sprintf {|@echo off
setlocal EnableDelayedExpansion
-set firstboot=%s
-set log=%%firstboot%%\log.txt
+set "firstboot=%s"
+set "log=%%firstboot%%\log.txt"
-set scripts=%%firstboot%%\scripts
-set scripts_done=%%firstboot%%\scripts-done
+set "scripts=%%firstboot%%\scripts"
+set "scripts_done=%%firstboot%%\scripts-done"
call :main >> "%%log%%" 2>&1
exit /b
@@ -327,6 +330,10 @@ for %%%%f in ("%%scripts%%"\*.bat) do (
)
:: Fallthrough here if there are no scripts.
+
+:: Touch a sentinel file to say we have finished.
+type nul > "%%firstboot%%\complete"
+
echo uninstalling firstboot service
"%%firstboot%%\%s" -s firstboot uninstall
|} firstboot_dir_win srvany in
diff --git a/common/mlcustomize/hostname.ml b/common/mlcustomize/hostname.ml
index d4a13d4d4..66f59a322 100644
--- a/common/mlcustomize/hostname.ml
+++ b/common/mlcustomize/hostname.ml
@@ -37,7 +37,7 @@ let rec set_hostname (g : Guestfs.guestfs) root hostname =
true
| "linux", ("rhel"|"centos"|"scientificlinux"|"oraclelinux"|"rocky"|
- "redhat-based"|"openeuler"), v
+ "redhat-based"|"openeuler"|"kylin"|"neokylin"|"anolis"), v
when v >= 7 ->
update_etc_hostname g hostname;
update_etc_machine_info g hostname;
@@ -50,7 +50,7 @@ let rec set_hostname (g : Guestfs.guestfs) root hostname =
true
| "linux", ("fedora"|"rhel"|"centos"|"scientificlinux"|"oraclelinux"|
- "redhat-based"|"openeuler"), _ ->
+ "redhat-based"|"openeuler"|"kylin"|"neokylin"|"anolis"), _ ->
replace_line_in_file g "/etc/sysconfig/network" "HOSTNAME" hostname;
true
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
index 114df0641..a29380806 100644
--- a/common/mlcustomize/inject_virtio_win.ml
+++ b/common/mlcustomize/inject_virtio_win.ml
@@ -254,13 +254,10 @@ and inject_qemu_ga ({ g; root } as t) =
and inject_blnsvr ({ g; root } as t) =
(* Copy the files to the guest. *)
- let dir, dir_win = Firstboot.firstboot_dir g root in
- let dir_win = Option.value dir_win ~default:dir in
- let tempdir = sprintf "%s/Temp" dir in
- let tempdir_win = sprintf "%s\\Temp" dir_win in
- g#mkdir_p tempdir;
+ let driverdir = sprintf "%s/Drivers/VirtIO" t.i_windows_systemroot in
+ g#mkdir_p driverdir;
- let files = copy_blnsvr t tempdir in
+ let files = copy_blnsvr t driverdir in
match files with
| [] -> false (* Didn't find or install anything. *)
@@ -268,7 +265,7 @@ and inject_blnsvr ({ g; root } as t) =
* drivers/by-driver). Pick the first.
*)
| blnsvr :: _ ->
- configure_blnsvr t tempdir_win blnsvr;
+ configure_blnsvr t driverdir blnsvr;
true
and add_guestor_to_registry t ((g, root) as reg) drv_name drv_pciid =
@@ -570,9 +567,9 @@ and configure_qemu_ga t tempdir_win files =
Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga" !script
-and configure_blnsvr t tempdir_win blnsvr =
+and configure_blnsvr t driverdir blnsvr =
let cmd = sprintf "\
@echo off\n\
echo Installing %s\n\
- \"%s\\%s\" -i\n" blnsvr tempdir_win blnsvr in
+ \"%s\\%s\" -i\n" blnsvr driverdir blnsvr in
Firstboot.add_firstboot_script t.g t.root "install-blnsvr" cmd
diff --git a/common/mlcustomize/password.ml b/common/mlcustomize/password.ml
index 62f80b05f..8dba0358a 100644
--- a/common/mlcustomize/password.ml
+++ b/common/mlcustomize/password.ml
@@ -190,6 +190,7 @@ and default_crypto g root =
(* Rolling distributions, which hopefully should be updated enough. *)
| ("archlinux"|"kalilinux"), _ -> `YESCRYPT
| ("voidlinux"|"openeuler"), _ -> `SHA512
+ | ("kylin"|"neokylin"|"anolis"), _ -> `SHA512
| _, _ ->
let minor = g#inspect_get_minor_version root in
diff --git a/common/mldrivers/Makefile.am b/common/mldrivers/Makefile.am
index 714fc9f74..aac3da4f1 100644
--- a/common/mldrivers/Makefile.am
+++ b/common/mldrivers/Makefile.am
@@ -94,7 +94,7 @@ endif
libmldrivers_a_DEPENDENCIES = $(OBJECTS)
$(MLDRIVERS_CMA): $(OBJECTS) libmldrivers.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmldrivers_a_OBJECTS) -o mldrivers
# OCaml dependencies.
diff --git a/common/mlgettext/Makefile.am b/common/mlgettext/Makefile.am
index 712feb11b..275b15fa2 100644
--- a/common/mlgettext/Makefile.am
+++ b/common/mlgettext/Makefile.am
@@ -71,11 +71,11 @@ endif
libmlgettext_a_DEPENDENCIES = $(OBJECTS)
mlgettext.cma: $(BOBJECTS)
- $(OCAMLFIND) ocamlc $(OCAMLPACKAGES) -a $^ -o $@
+ $(AM_V_GEN) $(OCAMLFIND) ocamlc $(OCAMLPACKAGES) -a $^ -o $@
if HAVE_OCAMLOPT
mlgettext.cmxa: $(XOBJECTS)
- $(OCAMLFIND) ocamlopt $(OCAMLPACKAGES) -a $^ -o $@
+ $(AM_V_GEN) $(OCAMLFIND) ocamlopt $(OCAMLPACKAGES) -a $^ -o $@
endif
# Dependencies.
diff --git a/common/mlpcre/Makefile.am b/common/mlpcre/Makefile.am
index a1d8b0293..30a60f645 100644
--- a/common/mlpcre/Makefile.am
+++ b/common/mlpcre/Makefile.am
@@ -83,7 +83,7 @@ endif
libmlpcre_a_DEPENDENCIES = $(OBJECTS)
$(MLPCRE_CMA): $(OBJECTS) libmlpcre.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlpcre_a_OBJECTS) -cclib -lpcre2-8 -o mlpcre
# Tests.
diff --git a/common/mlpcre/PCRE.ml b/common/mlpcre/PCRE.ml
index 077290ef1..33074af1c 100644
--- a/common/mlpcre/PCRE.ml
+++ b/common/mlpcre/PCRE.ml
@@ -22,7 +22,7 @@ exception Error of string * int
type regexp
-external compile : ?caseless:bool -> ?dotall:bool -> ?extended:bool -> ?multiline:bool -> string -> regexp = "guestfs_int_pcre_compile"
+external compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool -> ?extended:bool -> ?multiline:bool -> string -> regexp = "guestfs_int_pcre_compile_byte" "guestfs_int_pcre_compile"
external matches : ?offset:int -> regexp -> string -> bool = "guestfs_int_pcre_matches"
external sub : int -> string = "guestfs_int_pcre_sub"
external subi : int -> int * int = "guestfs_int_pcre_subi"
diff --git a/common/mlpcre/PCRE.mli b/common/mlpcre/PCRE.mli
index b69a56ba9..0fdc2bd5f 100644
--- a/common/mlpcre/PCRE.mli
+++ b/common/mlpcre/PCRE.mli
@@ -52,11 +52,12 @@ exception Error of string * int
type regexp
(** The type of a compiled regular expression. *)
-val compile : ?caseless:bool -> ?dotall:bool -> ?extended:bool -> ?multiline:bool -> string -> regexp
+val compile : ?anchored:bool -> ?caseless:bool -> ?dotall:bool ->
+ ?extended:bool -> ?multiline:bool -> string -> regexp
(** Compile a regular expression. This can raise {!Error}.
- The flags [?caseless], [?dotall], [?extended], [?multiline]
- correspond to the [pcre_compile] flags [PCRE_CASELESS] etc.
+ The flags [?anchored], [?caseless], [?dotall], [?extended], [?multiline]
+ correspond to the [pcre_compile] flags [PCRE_ANCHORED] etc.
See pcre2api(3) for details of what they do.
All flags default to false. *)
diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c
index 3959fd566..11be15775 100644
--- a/common/mlpcre/pcre-c.c
+++ b/common/mlpcre/pcre-c.c
@@ -154,11 +154,12 @@ Optint_val (value intv, int defval)
}
value
-guestfs_int_pcre_compile (value caselessv, value dotallv,
- value extendedv, value multilinev,
+guestfs_int_pcre_compile (value anchoredv, value caselessv,
+ value dotallv, value extendedv,
+ value multilinev,
value pattv)
{
- CAMLparam4 (caselessv, dotallv, extendedv, multilinev);
+ CAMLparam5 (anchoredv, caselessv, dotallv, extendedv, multilinev);
CAMLxparam1 (pattv);
const char *patt;
int options = 0;
@@ -167,6 +168,8 @@ guestfs_int_pcre_compile (value caselessv, value dotallv,
PCRE2_SIZE errnum;
/* Flag parameters are all bool option, defaulting to false. */
+ if (is_Some_true (anchoredv))
+ options |= PCRE2_ANCHORED;
if (is_Some_true (caselessv))
options |= PCRE2_CASELESS;
if (is_Some_true (dotallv))
@@ -186,6 +189,14 @@ guestfs_int_pcre_compile (value caselessv, value dotallv,
CAMLreturn (Val_regexp (re));
}
+value
+guestfs_int_pcre_compile_byte (value *argv, int argn)
+{
+ assert (argn == 6);
+ return guestfs_int_pcre_compile (argv[0], argv[1], argv[2],
+ argv[3], argv[4], argv[5]);
+}
+
value
guestfs_int_pcre_matches (value offsetv, value rev, value strv)
{
diff --git a/common/mlprogress/Makefile.am b/common/mlprogress/Makefile.am
index 3f3424e04..134c4ab4c 100644
--- a/common/mlprogress/Makefile.am
+++ b/common/mlprogress/Makefile.am
@@ -83,7 +83,7 @@ endif
libmlprogress_a_DEPENDENCIES = $(OBJECTS)
$(MLPROGRESS_CMA): $(OBJECTS) libmlprogress.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlprogress_a_OBJECTS) \
-cclib -lprogress \
-o mlprogress
diff --git a/common/mlstdutils/Makefile.am b/common/mlstdutils/Makefile.am
index b9632b078..0f881907a 100644
--- a/common/mlstdutils/Makefile.am
+++ b/common/mlstdutils/Makefile.am
@@ -84,11 +84,11 @@ endif
libmlstdutils_a_DEPENDENCIES = $(OBJECTS)
mlstdutils.cma: $(BOBJECTS)
- $(OCAMLFIND) ocamlc $(OCAMLPACKAGES) -a $^ -o $@
+ $(AM_V_GEN) $(OCAMLFIND) ocamlc $(OCAMLPACKAGES) -a $^ -o $@
if HAVE_OCAMLOPT
mlstdutils.cmxa: $(XOBJECTS)
- $(OCAMLFIND) ocamlopt $(OCAMLPACKAGES) -a $^ -o $@
+ $(AM_V_GEN) $(OCAMLFIND) ocamlopt $(OCAMLPACKAGES) -a $^ -o $@
endif
# Tests.
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index 6c1911da8..77cf107ed 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -51,6 +51,7 @@ module List : sig
val find_all : ('a -> bool) -> 'a list -> 'a list
val partition : ('a -> bool) -> 'a list -> 'a list * 'a list
val assoc : 'a -> ('a * 'b) list -> 'b
+ val assoc_opt : 'a -> ('a * 'b) list -> 'b option
val assq : 'a -> ('a * 'b) list -> 'b
val mem_assoc : 'a -> ('a * 'b) list -> bool
val mem_assq : 'a -> ('a * 'b) list -> bool
diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am
index e9e0398c7..44cfbb1b1 100644
--- a/common/mltools/Makefile.am
+++ b/common/mltools/Makefile.am
@@ -161,7 +161,7 @@ endif
libmltools_a_DEPENDENCIES = $(OBJECTS)
$(MLTOOLS_CMA): $(OBJECTS) libmltools.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmltools_a_OBJECTS) -o mltools
# Tests.
diff --git a/common/mltools/tools_utils-c.c b/common/mltools/tools_utils-c.c
index 4ff42e5d5..21f7469aa 100644
--- a/common/mltools/tools_utils-c.c
+++ b/common/mltools/tools_utils-c.c
@@ -126,10 +126,10 @@ guestfs_int_mllib_rfc3339_date_time_string (value unitv)
size_t total = 0;
if (clock_gettime (CLOCK_REALTIME, &ts) == -1)
- unix_error (errno, (char *) "clock_gettime", Val_unit);
+ caml_unix_error (errno, (char *) "clock_gettime", Val_unit);
if (localtime_r (&ts.tv_sec, &tm) == NULL)
- unix_error (errno, (char *) "localtime_r", caml_copy_int64 (ts.tv_sec));
+ caml_unix_error (errno, (char *) "localtime_r", caml_copy_int64 (ts.tv_sec));
/* Sadly strftime does not support nanoseconds, so what we do is:
* - stringify everything before the nanoseconds
@@ -141,17 +141,17 @@ guestfs_int_mllib_rfc3339_date_time_string (value unitv)
ret = strftime (buf, sizeof (buf), "%Y-%m-%dT%H:%M:%S.", &tm);
if (ret == 0)
- unix_error (errno, (char *) "strftime", Val_unit);
+ caml_unix_error (errno, (char *) "strftime", Val_unit);
total += ret;
ret = snprintf (buf + total, sizeof (buf) - total, "%09ld", ts.tv_nsec);
if (ret == 0)
- unix_error (errno, (char *) "sprintf", caml_copy_int64 (ts.tv_nsec));
+ caml_unix_error (errno, (char *) "sprintf", caml_copy_int64 (ts.tv_nsec));
total += ret;
ret = strftime (buf + total, sizeof (buf) - total, "%z", &tm);
if (ret == 0)
- unix_error (errno, (char *) "strftime", Val_unit);
+ caml_unix_error (errno, (char *) "strftime", Val_unit);
total += ret;
/* Move the timezone minutes one character to the right, moving the
diff --git a/common/mlutils/Makefile.am b/common/mlutils/Makefile.am
index d52cb9c86..084ce6304 100644
--- a/common/mlutils/Makefile.am
+++ b/common/mlutils/Makefile.am
@@ -86,7 +86,7 @@ endif
libmlcutils_a_DEPENDENCIES = $(OBJECTS)
$(MLCUTILS_CMA): $(OBJECTS) libmlcutils.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlcutils_a_OBJECTS) \
-cclib -lutils \
-o mlcutils
diff --git a/common/mlutils/c_utils-c.c b/common/mlutils/c_utils-c.c
index d9c1a4803..f0e2798f4 100644
--- a/common/mlutils/c_utils-c.c
+++ b/common/mlutils/c_utils-c.c
@@ -68,7 +68,7 @@ guestfs_int_mlutils_shell_unquote (value strv)
ret = guestfs_int_shell_unquote (String_val (strv));
if (ret == NULL)
- unix_error (errno, (char *) "guestfs_int_shell_unquote", Nothing);
+ caml_unix_error (errno, (char *) "guestfs_int_shell_unquote", Nothing);
retv = caml_copy_string (ret);
free (ret);
@@ -101,6 +101,8 @@ guestfs_int_mlutils_full_path (value dirv, value namev)
name = String_val (Field (namev, 0));
ret = guestfs_int_full_path (String_val (dirv), name);
+ if (ret == NULL)
+ caml_unix_error (errno, (char *) "guestfs_int_full_path", dirv);
rv = caml_copy_string (ret);
free (ret);
diff --git a/common/mlutils/unix_utils-c.c b/common/mlutils/unix_utils-c.c
index ee5a37964..28df2c310 100644
--- a/common/mlutils/unix_utils-c.c
+++ b/common/mlutils/unix_utils-c.c
@@ -147,7 +147,7 @@ guestfs_int_mllib_fnmatch (value patternv, value strv, value flagsv)
/* XXX The fnmatch specification doesn't mention what errors can
* be returned by fnmatch. Assume they are errnos for now.
*/
- unix_error (errno, (char *) "fnmatch", patternv);
+ caml_unix_error (errno, (char *) "fnmatch", patternv);
}
}
@@ -180,16 +180,16 @@ guestfs_int_mllib_fsync_file (value filenamev)
/* Note to do fsync you have to open for write. */
fd = open (filename, O_RDWR);
if (fd == -1)
- unix_error (errno, (char *) "open", filenamev);
+ caml_unix_error (errno, (char *) "open", filenamev);
if (fsync (fd) == -1) {
err = errno;
close (fd);
- unix_error (err, (char *) "fsync", filenamev);
+ caml_unix_error (err, (char *) "fsync", filenamev);
}
if (close (fd) == -1)
- unix_error (errno, (char *) "close", filenamev);
+ caml_unix_error (errno, (char *) "close", filenamev);
CAMLreturn (Val_unit);
}
@@ -203,11 +203,14 @@ guestfs_int_mllib_mkdtemp (value val_pattern)
pattern = strdup (String_val (val_pattern));
if (pattern == NULL)
- unix_error (errno, (char *) "strdup", val_pattern);
+ caml_unix_error (errno, (char *) "strdup", val_pattern);
ret = mkdtemp (pattern);
- if (ret == NULL)
- unix_error (errno, (char *) "mkdtemp", val_pattern);
+ if (ret == NULL) {
+ int err = errno;
+ free (pattern);
+ caml_unix_error (err, (char *) "mkdtemp", val_pattern);
+ }
rv = caml_copy_string (ret);
free (pattern);
@@ -224,7 +227,7 @@ guestfs_int_mllib_realpath (value pathv)
r = realpath (String_val (pathv), NULL);
if (r == NULL)
- unix_error (errno, (char *) "realpath", pathv);
+ caml_unix_error (errno, (char *) "realpath", pathv);
rv = caml_copy_string (r);
free (r);
@@ -252,7 +255,7 @@ guestfs_int_mllib_statvfs_statvfs (value pathv)
struct statvfs buf;
if (statvfs (String_val (pathv), &buf) == -1)
- unix_error (errno, (char *) "statvfs", pathv);
+ caml_unix_error (errno, (char *) "statvfs", pathv);
f_bsize = buf.f_bsize;
f_frsize = buf.f_frsize;
@@ -276,7 +279,7 @@ guestfs_int_mllib_statvfs_statvfs (value pathv)
(PULARGE_INTEGER) &free_bytes_available,
(PULARGE_INTEGER) &total_number_of_bytes,
(PULARGE_INTEGER) &total_number_of_free_bytes))
- unix_error (EIO, (char *) "statvfs: GetDiskFreeSpaceEx", pathv);
+ caml_unix_error (EIO, (char *) "statvfs: GetDiskFreeSpaceEx", pathv);
/* XXX I couldn't determine how to get block size. MSDN has a
* unhelpful hard-coded list here:
@@ -341,15 +344,17 @@ guestfs_int_mllib_statvfs_statvfs (value pathv)
CAMLreturn (rv);
}
-/* NB: This is a [@@noalloc] call. */
value
guestfs_int_mllib_statvfs_is_network_filesystem (value pathv)
{
+ CAMLparam1 (pathv);
+ CAMLlocal1 (rv);
+
#ifdef HAVE_STATFS
struct statfs buf;
if (statfs (String_val (pathv), &buf) == -1)
- unix_error (errno, (char *) "statvfs", pathv);
+ caml_unix_error (errno, (char *) "statvfs", pathv);
/* Some but not all of these are defined in <linux/magic.h>. */
#ifndef CIFS_MAGIC_NUMBER
@@ -362,12 +367,14 @@ guestfs_int_mllib_statvfs_is_network_filesystem (value pathv)
#define SMB_SUPER_MAGIC 0x517b
#endif
- return Val_bool ((unsigned int) buf.f_type == CIFS_MAGIC_NUMBER ||
- (unsigned int) buf.f_type == NFS_SUPER_MAGIC ||
- (unsigned int) buf.f_type == SMB_SUPER_MAGIC);
+ rv = Val_bool ((unsigned int) buf.f_type == CIFS_MAGIC_NUMBER ||
+ (unsigned int) buf.f_type == NFS_SUPER_MAGIC ||
+ (unsigned int) buf.f_type == SMB_SUPER_MAGIC);
#else
- return Val_bool (0);
+ rv = Val_bool (0);
#endif
+
+ CAMLreturn (rv);
}
/* NB: This is a [@@noalloc] call. */
diff --git a/common/mlutils/unix_utils.ml b/common/mlutils/unix_utils.ml
index b79144a98..5898cbec7 100644
--- a/common/mlutils/unix_utils.ml
+++ b/common/mlutils/unix_utils.ml
@@ -82,7 +82,7 @@ module StatVFS = struct
let free_space { f_bsize = bsize; f_bavail = bavail } = bsize *^ bavail
external is_network_filesystem : string -> bool =
- "guestfs_int_mllib_statvfs_is_network_filesystem" [@@noalloc]
+ "guestfs_int_mllib_statvfs_is_network_filesystem"
end
module Sysconf = struct
diff --git a/common/mlvisit/Makefile.am b/common/mlvisit/Makefile.am
index beff0bc64..40ecb0f76 100644
--- a/common/mlvisit/Makefile.am
+++ b/common/mlvisit/Makefile.am
@@ -88,7 +88,7 @@ endif
libmlvisit_a_DEPENDENCIES = $(OBJECTS)
$(MLVISIT_CMA): $(OBJECTS) libmlvisit.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlvisit_a_OBJECTS) -cclib -lvisit -o mlvisit
# Tests.
diff --git a/common/mlxml/Makefile.am b/common/mlxml/Makefile.am
index e56b6fd54..db131ab30 100644
--- a/common/mlxml/Makefile.am
+++ b/common/mlxml/Makefile.am
@@ -84,7 +84,7 @@ endif
libmlxml_a_DEPENDENCIES = $(OBJECTS)
$(MLXML_CMA): $(OBJECTS) libmlxml.a
- $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
+ $(AM_V_GEN) $(OCAMLFIND) mklib $(OCAMLPACKAGES) \
$(OBJECTS) $(libmlxml_a_OBJECTS) \
-o mlxml
diff --git a/common/options/keys.c b/common/options/keys.c
index 7027104a9..b8f19cebf 100644
--- a/common/options/keys.c
+++ b/common/options/keys.c
@@ -78,6 +78,7 @@ read_key (const char *param)
len = getline (&ret, &allocsize, infp);
if (len == -1) {
perror ("getline");
+ free (ret);
ret = NULL;
goto error;
}
diff --git a/common/parallel/parallel.c b/common/parallel/parallel.c
index 18b060740..88ad819f0 100644
--- a/common/parallel/parallel.c
+++ b/common/parallel/parallel.c
@@ -221,6 +221,7 @@ worker_thread (void *thread_data_vp)
g = guestfs_create ();
if (g == NULL) {
perror ("guestfs_create");
+ fclose (fp);
thread_data->r = -1;
return &thread_data->r;
}

View File

@ -0,0 +1,119 @@
From b603dd04190ff1c7c71b04c135474859ccacd136 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 26 Mar 2026 13:02:45 +0000
Subject: [PATCH] common: update submodule
Cole Robinson (1):
Add update-submodule.sh
Richard W.M. Jones (3):
mlutils/unix_utils-c.c: Include "guestfs-utils.h"
mlcustomize: Remove fictitious "vista" virtio-win directory
mlcustomize: Use 2k8 drivers for Windows Vista and 2008 Server R1
(cherry picked from commit 6b8eb0742dab07ce0c90e0aa855f9ba85df89fb0)
---
Makefile.am | 1 +
common | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 7be3c1496..87cf2cdc7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -92,6 +92,7 @@ EXTRA_DIST = \
check-mli.sh \
common/.gitignore \
common/README \
+ common/update-submodule.sh \
lib/guestfs-internal-all.h \
m4/.gitignore \
podcheck.pl \
Submodule common c8e64b3ff..0948fc94a:
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
index a29380806..ce24332ff 100644
--- a/common/mlcustomize/inject_virtio_win.ml
+++ b/common/mlcustomize/inject_virtio_win.ml
@@ -468,10 +468,8 @@ and virtio_iso_path_matches_guest_os t path =
((=) "winxp")
else if pathelem "2k3" then
(function "win2k3" | "win2k3r2" -> true | _ -> false)
- else if pathelem "vista" then
- ((=) "winvista")
else if pathelem "2k8" then
- ((=) "win2k8")
+ (function "win2k8" | "winvista" -> true | _ -> false)
else if pathelem "w7" then
((=) "win7")
else if pathelem "2k8r2" then
diff --git a/common/mlutils/unix_utils-c.c b/common/mlutils/unix_utils-c.c
index 28df2c310..919f52602 100644
--- a/common/mlutils/unix_utils-c.c
+++ b/common/mlutils/unix_utils-c.c
@@ -65,6 +65,8 @@
#include <caml/mlvalues.h>
#include <caml/unixsupport.h>
+#include "guestfs-utils.h"
+
extern value guestfs_int_mllib_dev_t_makedev (value majv, value minv);
extern value guestfs_int_mllib_dev_t_major (value devv);
extern value guestfs_int_mllib_dev_t_minor (value devv);
diff --git a/common/update-submodule.sh b/common/update-submodule.sh
new file mode 100755
index 000000000..ecf22f166
--- /dev/null
+++ b/common/update-submodule.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# (C) Copyright 2026 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Generate a submodule update commit, with formatted shortlog output.
+# Run this from the parent repo like: ./common/update-submodule.sh
+# Then `git commit --amend ...` as desired.
+
+set -euo pipefail
+
+if ! git submodule status common &>/dev/null; then
+ echo "Error: this script must be run from the top directory of a repo with a 'common/' submodule" >&2
+ exit 1
+fi
+
+if ! git diff --quiet --exit-code; then
+ echo "Error: working tree has uncommitted changes" >&2
+ exit 1
+fi
+
+echo "Running: git submodule update --remote common"
+git submodule update --remote common
+
+if git diff --quiet --exit-code; then
+ echo "'common' submodule already up to date"
+ exit 0
+fi
+
+OLD_COMMIT=$(git ls-tree HEAD common | awk '{print $3}')
+NEW_COMMIT=$(git -C common rev-parse HEAD)
+echo "Old 'common' commit: $OLD_COMMIT"
+echo "New 'common' commit: $NEW_COMMIT"
+
+SHORTLOG=$(git -C common shortlog --no-merges "${OLD_COMMIT}..${NEW_COMMIT}" | sed '/^$/!s/^/ /')
+git commit -F - common <<EOF
+common: update submodule
+
+$SHORTLOG
+EOF

View File

@ -0,0 +1,483 @@
From ff7a1b942a667e3cfa5f382a543d775f6c3c8e9b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 28 Apr 2026 16:57:48 +0100
Subject: [PATCH] common: update submodule
Richard W.M. Jones (5):
mldrivers/firmware.ml: Ignore CHS geometry error from parted
utils: Add read_whole_file function
options/keys.c: When reading key from user, prefix with "text:"
options/keys.c: When using --key <dev>:key:<string>, prefix with "text:"
options/keys.c: When reading the key from a file, encode it with base64
Srihari Parimi (2):
mltools: add prefix to debug () output
mltools: for external commands include function name in debug() output
Susant Sahani (1):
smp: respect cgroup v2 CPU limits for appliance SMP
Also this now requires libguestfs >= 1.59.7 because we rely on text:
and base64: prefixes in LUKS functions.
Fixes: https://redhat.atlassian.net/browse/RHEL-171896
Cherry picked from commit 08afa63ea1541f5e9711d1c8be3b5806c226d539.
For RHEL 10.2, adjust minimum libguestfs version to match.
---
common | 2 +-
m4/guestfs-libraries.m4 | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
Submodule common 0948fc94a..cf2e12078:
diff --git a/common/mldrivers/firmware.ml b/common/mldrivers/firmware.ml
index ee0a7cafe..6698b0736 100644
--- a/common/mldrivers/firmware.ml
+++ b/common/mldrivers/firmware.ml
@@ -18,6 +18,7 @@
open Printf
+open Std_utils
open Tools_utils
module G = Guestfs
@@ -28,12 +29,22 @@ type i_firmware =
let detect_firmware g =
let parttype_is_gpt dev =
- try g#part_get_parttype dev = "gpt"
- with G.Error msg as exn ->
- (* If it's _not_ "unrecognised disk label" then re-raise it. *)
- if g#last_errno () <> G.Errno.errno_EINVAL then raise exn;
- debug "%s (ignored)" msg;
- false
+ try
+ g#part_get_parttype dev = "gpt"
+ with
+ | G.Error msg when String.find msg "CHS geometry" >= 0 ->
+ (* Parted has poor handling of "sun" partition types, always
+ * issuing a warning because the CHS doesn't match the physical
+ * geometry. Ignore this as we don't care about it in this
+ * function (RHEL-165220).
+ *)
+ debug "%s (ignored)" msg;
+ false
+ | G.Error msg as exn ->
+ (* If it's _not_ "unrecognised disk label" then re-raise it. *)
+ if g#last_errno () <> G.Errno.errno_EINVAL then raise exn;
+ debug "%s (ignored)" msg;
+ false
in
let accumulate_partition (esp_parts, bboot) part =
let dev = g#part_to_dev part in
diff --git a/common/mltools/tools_utils.ml b/common/mltools/tools_utils.ml
index 330ca3d00..b1938b5db 100644
--- a/common/mltools/tools_utils.ml
+++ b/common/mltools/tools_utils.ml
@@ -207,7 +207,10 @@ let info fs =
(* Print a debug message. *)
let debug fs =
- let display str = if verbose () then prerr_endline str in
+ let display str =
+ if verbose () then
+ prerr_endline (sprintf "%s: debug: %s" !prog str)
+ in
ksprintf display fs
(* Common function to create a new Guestfs handle, with common options
@@ -442,7 +445,7 @@ let external_command_failed help cmd reason =
(* Run an external command, slurp up the output as a list of lines. *)
let external_command ?(echo_cmd = true) ?help cmd =
if echo_cmd then
- debug "%s" cmd;
+ debug "external_command: %s" cmd;
let chan = Unix.open_process_in cmd in
let lines = ref [] in
(try while true do lines := input_line chan :: !lines done
@@ -517,7 +520,7 @@ and do_run ?(echo_cmd = true) ?help ?stdout_fd ?stderr_fd args =
let outfd = get_fd Unix.stdout stdout_fd in
let errfd = get_fd Unix.stderr stderr_fd in
if echo_cmd then
- debug "%s" (stringify_args args);
+ debug "run_command: %s" (stringify_args args);
let pid = Unix.create_process app (Array.of_list args) Unix.stdin
outfd errfd in
Either (pid, app, stdout_fd, stderr_fd)
@@ -544,7 +547,7 @@ and do_teardown help app outfd errfd exitstat =
let shell_command ?(echo_cmd = true) cmd =
if echo_cmd then
- debug "%s" cmd;
+ debug "shell_command: %s" cmd;
Sys.command cmd
(* Run uuidgen to return a random UUID. *)
diff --git a/common/mlutils/unix_utils.ml b/common/mlutils/unix_utils.ml
index 5898cbec7..9d7e11a65 100644
--- a/common/mlutils/unix_utils.ml
+++ b/common/mlutils/unix_utils.ml
@@ -89,3 +89,28 @@ module Sysconf = struct
external nr_processors_online : unit -> int =
"guestfs_int_mllib_sysconf_nr_processors_online" [@@noalloc]
end
+
+module Cgroup = struct
+ let v2_cpus () =
+ let file = "/sys/fs/cgroup/cpu.max" in
+ if Sys.file_exists file then
+ try
+ let line = read_first_line_from_file file in
+ if String.starts_with ~prefix:"max" line then
+ None
+ else
+ let quota, period =
+ Scanf.sscanf line "%Ld %Ld" (fun q p -> (q, p)) in
+ if period > 0L then
+ Some (max 1 (Int64.to_int (Int64.div quota period)))
+ else None
+ with
+ | Scanf.Scan_failure _ | Failure _ | End_of_file -> None
+ else
+ None
+
+ let nr_cpus_available () =
+ match v2_cpus () with
+ | Some cpus -> cpus
+ | None -> Sysconf.nr_processors_online ()
+end
diff --git a/common/mlutils/unix_utils.mli b/common/mlutils/unix_utils.mli
index aead4df21..cb4f0426e 100644
--- a/common/mlutils/unix_utils.mli
+++ b/common/mlutils/unix_utils.mli
@@ -130,3 +130,21 @@ module Sysconf : sig
Note this never fails. In case we cannot get the number of
cores it returns 1. *)
end
+
+module Cgroup : sig
+ (** Functions to read CPU limits from cgroup filesystems. *)
+
+ val v2_cpus : unit -> int option
+ (** [v2_cpus ()] reads the cgroup v2 CPU quota from
+ [/sys/fs/cgroup/cpu.max] and returns the number of CPUs
+ allocated (quota / period), or [None] if the file does not
+ exist, the quota is "max" (unlimited), or the file cannot
+ be parsed. The kernel stores quota and period as [long]
+ values in microseconds, so we parse them as [Int64]. *)
+
+ val nr_cpus_available : unit -> int
+ (** [nr_cpus_available ()] returns the number of CPUs available,
+ taking into account cgroup v2 CPU limits.
+ Falls back to {!Sysconf.nr_processors_online} if no cgroup
+ limits are set. *)
+end
diff --git a/common/options/keys.c b/common/options/keys.c
index b8f19cebf..432e26dc8 100644
--- a/common/options/keys.c
+++ b/common/options/keys.c
@@ -37,17 +37,23 @@
* Read a passphrase ('Key') from F</dev/tty> with echo off.
*
* The caller (F<fish/cmds.c>) will call free on the string
- * afterwards. Based on the code in cryptsetup file F<lib/utils.c>.
+ * afterwards.
+ *
+ * The entered string is prefixed with "text:..." to avoid ambiguity
+ * (with libguestfs >= 1.60). Base64 encoding cannot be used here.
+ *
+ * Based on the code in cryptsetup file F<lib/utils.c>.
*/
char *
read_key (const char *param)
{
FILE *infp, *outfp;
struct termios orig, temp;
+ CLEANUP_FREE char *key = NULL;
+ size_t keysize = 0;
char *ret = NULL;
int tty;
int tcset = 0;
- size_t allocsize = 0;
ssize_t len;
/* Read and write to /dev/tty if available. */
@@ -75,17 +81,21 @@ read_key (const char *param)
}
}
- len = getline (&ret, &allocsize, infp);
+ len = getline (&key, &keysize, infp);
if (len == -1) {
perror ("getline");
- free (ret);
- ret = NULL;
goto error;
}
/* Remove the terminating \n if there is one. */
- if (len > 0 && ret[len-1] == '\n')
- ret[len-1] = '\0';
+ if (len > 0 && key[len-1] == '\n')
+ key[len-1] = '\0';
+
+ /* Prefix with "text:". */
+ if (asprintf (&ret, "text:%s", key) == -1) {
+ perror ("asprintf");
+ goto error;
+ }
error:
/* Restore echo, close file descriptor. */
@@ -100,27 +110,60 @@ read_key (const char *param)
return ret;
}
+/* Read a key from a file and base64 encode it, returning "base64:..." */
static char *
-read_first_line_from_file (const char *filename)
+read_key_and_base64_encode (const char *filename)
{
- CLEANUP_FCLOSE FILE *fp = NULL;
- char *ret = NULL;
- size_t allocsize = 0;
- ssize_t len;
+ CLEANUP_FREE char *inp = NULL;
+ char *out;
+ size_t inplen, outlen, i, j;
- fp = fopen (filename, "r");
- if (!fp)
- error (EXIT_FAILURE, errno, "fopen: %s", filename);
+ if (read_whole_file (filename, &inp, &inplen) == -1)
+ error (EXIT_FAILURE, 0, "read_key_and_base64_encode: read_whole_file: %s",
+ filename);
- len = getline (&ret, &allocsize, fp);
- if (len == -1)
- error (EXIT_FAILURE, errno, "getline: %s", filename);
+ /* From https://stackoverflow.com/a/6782480 */
+ static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/'};
+ static int mod_table[] = {0, 2, 1};
- /* Remove the terminating \n if there is one. */
- if (len > 0 && ret[len-1] == '\n')
- ret[len-1] = '\0';
+ outlen = 4 * ((inplen + 2) / 3);
+ out = malloc (outlen + 7 + 1);
+ if (!out)
+ error (EXIT_FAILURE, errno, "read_key_and_base64_encode: %s: malloc",
+ filename);
- return ret;
+ /* Add prefix and NUL-termination, then adjust 'out' to make the
+ * rest of the code simpler.
+ */
+ memcpy (out, "base64:", 7);
+ out[7 + outlen] = '\0';
+ out += 7;
+
+ for (i = 0, j = 0; i < inplen;) {
+ uint32_t octet_a = i < inplen ? (unsigned char) inp[i++] : 0;
+ uint32_t octet_b = i < inplen ? (unsigned char) inp[i++] : 0;
+ uint32_t octet_c = i < inplen ? (unsigned char) inp[i++] : 0;
+
+ uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
+
+ assert (j <= outlen-4);
+ out[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
+ out[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
+ out[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
+ out[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
+ }
+
+ for (i = 0; i < mod_table[inplen % 3]; i++)
+ out[outlen - 1 - i] = '=';
+
+ return out - 7 /* see above */;
}
/* Return the key(s) matching this particular device from the
@@ -164,15 +207,14 @@ get_keys (struct key_store *ks, const char *device, const char *uuid,
switch (key->type) {
case key_string:
- s = strdup (key->string.s);
- if (!s)
- error (EXIT_FAILURE, errno, "strdup");
+ if (asprintf (&s, "text:%s", key->string.s) == -1)
+ error (EXIT_FAILURE, errno, "asprintf");
match->clevis = false;
match->passphrase = s;
++match;
break;
case key_file:
- s = read_first_line_from_file (key->file.name);
+ s = read_key_and_base64_encode (key->file.name);
match->clevis = false;
match->passphrase = s;
++match;
diff --git a/common/utils/Makefile.am b/common/utils/Makefile.am
index 25c6100b2..f328dcadf 100644
--- a/common/utils/Makefile.am
+++ b/common/utils/Makefile.am
@@ -30,6 +30,7 @@ libutils_la_SOURCES = \
libxml2-writer-macros.h \
pcre2-cleanups.c \
stringlists-utils.c \
+ whole-file.c \
utils.c
libutils_la_CPPFLAGS = \
-DGUESTFS_NO_DEPRECATED=1 \
diff --git a/common/utils/guestfs-utils.h b/common/utils/guestfs-utils.h
index e861e7db5..a8bd9ac2c 100644
--- a/common/utils/guestfs-utils.h
+++ b/common/utils/guestfs-utils.h
@@ -113,4 +113,8 @@ extern const char *guestfs_int_strerror (int errnum, char *buf, size_t buflen);
/* environ.c */
extern char **guestfs_int_copy_environ (char **env, ...);
+/* whole-file.c */
+extern int read_whole_file (const char *filename,
+ char **data_r, size_t *size_r);
+
#endif /* GUESTFS_UTILS_H_ */
diff --git a/common/utils/whole-file.c b/common/utils/whole-file.c
new file mode 100644
index 000000000..a896e0241
--- /dev/null
+++ b/common/utils/whole-file.c
@@ -0,0 +1,111 @@
+/* libguestfs
+ * Copyright (C) 2011-2026 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <libintl.h>
+
+#include "guestfs-utils.h"
+
+/**
+ * Read the whole file C<filename> into a memory buffer.
+ *
+ * The memory buffer is initialized and returned in C<data_r>. The
+ * size of the file in bytes is returned in C<size_r>. The return
+ * buffer must be freed by the caller.
+ *
+ * On error this prints an error on C<stderr> and returns -1. Unlike
+ * the similar C<guestfs_int_read_whole_file> this does not use the
+ * libguestfs handle or call C<error()>.
+ *
+ * For the convenience of callers, the returned buffer is
+ * NUL-terminated (the NUL is not included in the size).
+ *
+ * The file must be a B<regular>, B<local>, B<trusted> file. In
+ * particular, do not use this function to read files that might be
+ * under control of an untrusted user since that will lead to a
+ * denial-of-service attack.
+ */
+int
+read_whole_file (const char *filename, char **data_r, size_t *size_r)
+{
+ int fd;
+ char *data;
+ off_t size;
+ off_t n;
+ ssize_t r;
+ struct stat statbuf;
+
+ fd = open (filename, O_RDONLY|O_CLOEXEC);
+ if (fd == -1) {
+ perror (filename);
+ return -1;
+ }
+
+ if (fstat (fd, &statbuf) == -1) {
+ perror (filename);
+ close (fd);
+ return -1;
+ }
+
+ size = statbuf.st_size;
+ data = malloc (size + 1);
+ if (data == NULL) {
+ perror ("malloc");
+ close (fd);
+ return -1;
+ }
+
+ n = 0;
+ while (n < size) {
+ r = read (fd, &data[n], size - n);
+ if (r == -1) {
+ perror (filename);
+ free (data);
+ close (fd);
+ return -1;
+ }
+ if (r == 0) {
+ fprintf (stderr, "%s: unexpected end of input", filename);
+ free (data);
+ close (fd);
+ return -1;
+ }
+ n += r;
+ }
+
+ if (close (fd) == -1) {
+ perror (filename);
+ free (data);
+ return -1;
+ }
+
+ /* For convenience of callers, \0-terminate the data. */
+ data[size] = '\0';
+
+ *data_r = data;
+ if (size_r != NULL)
+ *size_r = size;
+
+ return 0;
+}
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 02f2281f8..9b643650d 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -22,7 +22,8 @@ dnl
dnl We need libguestfs 1.57.1 for guestfs_setfiles.
dnl We need libguestfs 1.57.6 for guestfs_inspect_get_applications2 app2_class.
dnl We need libguestfs 1.57.6 for guestfs_inspect_get_windows_group_policy
-PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.57.6])
+dnl We need libguestfs 1.58.1-6.el10 for text: and base64: prefix in LUKS funcs.
+PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.58.1])
printf "libguestfs version is "; $PKG_CONFIG --modversion libguestfs
dnl Test if it's GNU or XSI strerror_r.

View File

@ -0,0 +1,39 @@
From 0f1e772fcf18fc87fd3f4c98566358963893c715 Mon Sep 17 00:00:00 2001
From: Srihari Parimi <sparimi@redhat.com>
Date: Fri, 1 May 2026 15:04:41 +0530
Subject: [PATCH] virt-builder: document Windows firstboot exit code behavior
In the FIRST BOOT SCRIPTS section of the man page, update the
Windows-specific documentation to clarify how exit codes are handled.
Specifically, explain that for Windows guests, the firstboot.bat
script considers any exit code other than 249 as a success. An exit
code of 249 is treated as a failure, which triggers a retry of the
script on the next boot.
Fixes: https://redhat.atlassian.net/browse/RHEL-170708
(cherry picked from commit da6500b696d2c8d7614adb68a307651fe84663d6)
---
builder/virt-builder.pod | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index f043939ca..59dd197f0 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -873,6 +873,15 @@ F<rhsrvany.exe> or F<pvvxsvc.exe> is copied from the location pointed to by the
C<VIRT_TOOLS_DATA_DIR> environment variable; if not set, a compiled-in
default will be used (something like F</usr/share/virt-tools>).
+On Windows guests, firstboot scripts are executed by a dedicated
+C<firstboot.bat> script which manages the execution flow.
+
+This script monitors the exit code of each firstboot task. Any exit
+code other than B<249> is considered a success, and the script moves
+on to the next task. If a script returns B<249>, it is treated as a
+failure, and the system will attempt to run that script again on the
+next boot.
+
The output of the first boot scripts is available in the guest as
F<C:\Program Files\Guestfs\Firstboot\log.txt>.

View File

@ -0,0 +1,61 @@
From bdd1c1465eab264e50767c2a2d67d6a346033fcf Mon Sep 17 00:00:00 2001
From: Srihari Parimi <sparimi@redhat.com>
Date: Fri, 1 May 2026 20:20:47 +0530
Subject: [PATCH] virt-builder: document exit code 250 for Windows firstboot
Update the FIRST BOOT SCRIPTS section in virt-builder.pod to
document the behavior of exit code 250 for Windows guests.
Code 250 explicitly indicates that a reboot is not required,
allowing firstboot.bat to proceed to the next script without
shutting down. The section is now organized into a bulleted
list for better readability, covering codes 250, 249
(failure/retry), and general success codes.
Fixes: https://redhat.atlassian.net/browse/RHEL-170706
(cherry picked from commit 0fa9030e97e419fc03f61842e9e6df689623d345)
---
builder/virt-builder.pod | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index 59dd197f0..fcffecbee 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -874,13 +874,30 @@ C<VIRT_TOOLS_DATA_DIR> environment variable; if not set, a compiled-in
default will be used (something like F</usr/share/virt-tools>).
On Windows guests, firstboot scripts are executed by a dedicated
-C<firstboot.bat> script which manages the execution flow.
+C<firstboot.bat> script which manages the execution flow. It monitors
+the exit code of each firstboot script:
-This script monitors the exit code of each firstboot task. Any exit
-code other than B<249> is considered a success, and the script moves
-on to the next task. If a script returns B<249>, it is treated as a
-failure, and the system will attempt to run that script again on the
-next boot.
+=over 4
+
+=item * B<250>
+
+The script indicates that a system reboot is not required at
+this stage. The C<firstboot.bat> script will continue
+immediately to the next script in the sequence without
+initiating a shutdown.
+
+=item * B<249>
+
+The script is treated as a failure. The C<firstboot.bat> script
+stops execution, and the system will attempt to run this script
+again on the next boot.
+
+=item * B<Any other code>
+
+The script is considered a success. The C<firstboot.bat> script
+proceeds to the next script in the sequence.
+
+=back
The output of the first boot scripts is available in the guest as
F<C:\Program Files\Guestfs\Firstboot\log.txt>.

View File

@ -0,0 +1,43 @@
From 0a3e2281c04fa4bffeaac1a2fd4c5a8234c2e1ab Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 1 May 2026 16:35:25 +0100
Subject: [PATCH] common: update submodule
Srihari Parimi (1):
mlcustomize: firstboot.bat must not reboot VM on error code 250
(cherry picked from commit a4bc0acf3707b14bcaee237a3c9a7f8f5dd13ff9)
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common cf2e12078..228449739:
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index 543e98fb1..366beca9e 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -320,13 +320,18 @@ for %%%%f in ("%%scripts%%"\*.bat) do (
echo Script failed, will retry on next boot
)
- :: Reboot the computer. This is necessary to free any locked
- :: files which may prevent later scripts from running.
- shutdown /r /t 0 /y
+ :: Reboot the computer only if exit code indicates.
+ :: Exit code 250 means do not reboot, otherwise reboot
+ :: Reboot is necessary to free any locked files which
+ :: may prevent later scripts from running.
+ if !elvl! NEQ 250 (
+ shutdown /r /t 0 /y
- :: Exit the script (in case shutdown returns before rebooting).
- :: On next boot, the whole firstboot service will be called again.
- exit /b
+ :: Exit the script (in case shutdown returns before rebooting).
+ :: On next boot, the whole firstboot service will be called again.
+
+ exit /b
+ )
)
:: Fallthrough here if there are no scripts.

View File

@ -0,0 +1,223 @@
From 9c9877bf262d69b1ab6b265bb17dc3f009dcfffa Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2026 12:02:11 +0100
Subject: [PATCH] sysprep: Remove documentation about copying and cloning
This documentation is mostly obsolete and doesn't really cover any
useful use cases these days. It's best to remove it rather than
trying to keep it up to date.
(cherry picked from commit 82edee0cdcb8b0b8cb93d3067b311e8a13bd7a66)
---
sysprep/virt-sysprep.pod | 191 +--------------------------------------
1 file changed, 1 insertion(+), 190 deletions(-)
diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod
index f044998cc..6b913ad70 100644
--- a/sysprep/virt-sysprep.pod
+++ b/sysprep/virt-sysprep.pod
@@ -19,8 +19,7 @@ can be enabled or disabled as required.
Virt-sysprep modifies the guest or disk image I<in place>. The guest
must be shut down. If you want to preserve the existing contents of
-the guest, I<you must snapshot, copy or clone the disk first>. See
-L</COPYING AND CLONING> below.
+the guest, I<you must snapshot, copy or clone the disk first>.
You do I<not> need to run virt-sysprep as root. In fact we'd
generally recommend that you don't. The time you might want to run it
@@ -301,194 +300,6 @@ is given.
__OPERATIONS__
-=head1 COPYING AND CLONING
-
-Virt-sysprep can be used as part of a process of cloning guests, or to
-prepare a template from which guests can be cloned. There are many
-different ways to achieve this using the virt tools, and this section
-is just an introduction.
-
-A virtual machine (when switched off) consists of two parts:
-
-=over 4
-
-=item I<configuration>
-
-The configuration or description of the guest. eg. The libvirt
-XML (see C<virsh dumpxml>), the running configuration of the guest,
-or another external format like OVF.
-
-Some configuration items that might need to be changed:
-
-=over 4
-
-=item *
-
-name
-
-=item *
-
-UUID
-
-=item *
-
-path to block device(s)
-
-=item *
-
-network card MAC address
-
-=back
-
-=item I<block device(s)>
-
-One or more hard disk images, themselves containing files,
-directories, applications, kernels, configuration, etc.
-
-Some things inside the block devices that might need to be changed:
-
-=over 4
-
-=item *
-
-hostname and other net configuration
-
-=item *
-
-UUID
-
-=item *
-
-SSH host keys
-
-=item *
-
-Windows unique security ID (SID)
-
-=item *
-
-Puppet registration
-
-=back
-
-=back
-
-=head2 COPYING THE BLOCK DEVICE
-
-Starting with an original guest, you probably wish to copy the guest
-block device and its configuration to make a template. Then once you
-are happy with the template, you will want to make many clones from
-it.
-
- virt-sysprep
- |
- v
- original guest --------> template ---------->
- \------> cloned
- \-----> guests
- \---->
-
-You can, of course, just copy the block device on the host using
-L<cp(1)> or L<dd(1)>.
-
- dd dd
- original guest --------> template ---------->
- \------> cloned
- \-----> guests
- \---->
-
-There are some smarter (and faster) ways too:
-
- snapshot
- template ---------->
- \------> cloned
- \-----> guests
- \---->
-
-You may want to run virt-sysprep twice, once to reset the guest (to
-make a template) and a second time to customize the guest for a
-specific user:
-
- virt-sysprep virt-sysprep
- (reset) (add user, keys, logos)
- | |
- dd v dd v
- original guest ----> template ---------> copied ------> custom
- template guest
-
-=over 4
-
-=item *
-
-Create a snapshot using qemu-img:
-
- qemu-img create -f qcow2 -o backing_file=original snapshot.qcow
-
-The advantage is that you dont need to copy the original (very fast)
-and only changes are stored (less storage required).
-
-Note that writing to the backing file once you have created guests on
-top of it is not possible: you will corrupt the guests.
-
-=item *
-
-Create a snapshot using C<lvcreate --snapshot>.
-
-=item *
-
-Other ways to create snapshots include using filesystems-level tools
-(for filesystems such as btrfs).
-
-Most Network Attached Storage (NAS) devices can also create cheap
-snapshots from files or LUNs.
-
-=item *
-
-Get your NAS to duplicate the LUN. Most NAS devices can also
-duplicate LUNs very cheaply (they copy them on-demand in the
-background).
-
-=item *
-
-Prepare your template using L<virt-sparsify(1)>. See below.
-
-=back
-
-=head2 VIRT-CLONE
-
-A separate tool, L<virt-clone(1)>, can be used to duplicate the block
-device and/or modify the external libvirt configuration of a guest.
-It will reset the name, UUID and MAC address of the guest in the
-libvirt XML.
-
-L<virt-clone(1)> does not use libguestfs and cannot look inside the
-disk image. This was the original motivation to write virt-sysprep.
-
-=head2 SPARSIFY
-
- virt-sparsify
- original guest --------> template
-
-L<virt-sparsify(1)> can be used to make the cloning template smaller,
-making it easier to compress and/or faster to copy.
-
-Notice that since virt-sparsify also copies the image, you can use it
-to make the initial copy (instead of C<dd>).
-
-=head2 RESIZE
-
- virt-resize
- template ---------->
- \------> cloned
- \-----> guests
- \---->
-
-If you want to give people cloned guests, but let them pick the size
-of the guest themselves (eg. depending on how much they are prepared
-to pay for disk space), then instead of copying the template, you can
-run L<virt-resize(1)>. Virt-resize performs a copy and resize, and
-thus is ideal for cloning guests from a template.
-
=head1 FIRSTBOOT VS SCRIPT
The two options I<--firstboot> and I<--script> both supply shell

View File

@ -0,0 +1,39 @@
From c7e355b2abfaa0a29ce9bfaeab8883e2553cbee1 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2026 12:11:31 +0100
Subject: [PATCH] sysprep: Improve synopsis section
Expand the synopsis with more usage information. We cannot list all
the options here (eg. the customize options) because we don't
auto-generate that.
(cherry picked from commit e2b43bad4dc0176d2d43694b28b3d78e8fdcebc7)
---
sysprep/virt-sysprep.pod | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod
index 6b913ad70..799764c8e 100644
--- a/sysprep/virt-sysprep.pod
+++ b/sysprep/virt-sysprep.pod
@@ -4,9 +4,18 @@ virt-sysprep - Reset, unconfigure or customize a virtual machine so clones can b
=head1 SYNOPSIS
- virt-sysprep [--options] -d domname
+ virt-sysprep [--colors] [--colours] [-c URI] [--connect URI]
+ [-n] [--dry-run] [--enable OPERATIONS] [--operations OPERATIONS]
+ [--echo-keys] [--format raw|qcow2] [--key SELECTOR]
+ [--keys-from-stdin] [--mount-options] [-q] [--quiet]
+ [--network] [--no-network] [-v] [--verbose] [--wrap] [-x]
+ -d domname | -a disk.img [-a disk.img ...]
- virt-sysprep [--options] -a disk.img [-a disk.img ...]
+ virt-sysprep --list-operations
+
+ virt-sysprep --version
+
+ virt-sysprep -V
=head1 DESCRIPTION

View File

@ -0,0 +1,69 @@
From a22e17e45044cf1e3c116cc721b91ce1c9f4635d Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2026 12:12:12 +0100
Subject: [PATCH] sysprep: Rework documentation
Minor reworking:
- expand description
- combine multiple notes into one section
(cherry picked from commit b20cbdc6d003026403bedbe23e6c7841e22e324e)
---
sysprep/virt-sysprep.pod | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod
index 799764c8e..4f552b385 100644
--- a/sysprep/virt-sysprep.pod
+++ b/sysprep/virt-sysprep.pod
@@ -19,12 +19,13 @@ virt-sysprep - Reset, unconfigure or customize a virtual machine so clones can b
=head1 DESCRIPTION
-Virt-sysprep can reset or unconfigure a virtual machine so that
-clones can be made from it. Steps in this process include removing
-SSH host keys, removing persistent network MAC configuration, and
-removing user accounts. Virt-sysprep can also customize a virtual
-machine, for instance by adding SSH keys, users or logos. Each step
-can be enabled or disabled as required.
+Virt-sysprep can reset or unconfigure a virtual machine so that clones
+can be made from it, or to prepare a template from which clones can be
+made later on. Steps in this process include removing SSH host keys,
+removing persistent network MAC configuration, and removing user
+accounts. Virt-sysprep can also customize a virtual machine, for
+instance by adding SSH keys, users or logos. Each step can be enabled
+or disabled as required.
Virt-sysprep modifies the guest or disk image I<in place>. The guest
must be shut down. If you want to preserve the existing contents of
@@ -355,7 +356,7 @@ just deleting them. L<virt-sparsify(1)> is another way to remove this
content. See also the L<scrub(1)> command to get rid of deleted
content in directory entries and inodes.
-=head2 RANDOM SEED
+=head2 Random seed
I<(This section applies to Linux guests only)>
@@ -373,7 +374,9 @@ module:
cp template.img newguest.img
virt-sysprep --enable customize -a newguest.img
-=head1 SELINUX
+=head1 NOTES
+
+=head2 SELinux
For guests which make use of SELinux, special handling for them might
be needed when using operations which create new files or alter
@@ -381,7 +384,7 @@ existing ones.
For further details, see L<virt-builder(1)/SELINUX>.
-=head1 WINDOWS 8
+=head2 Windows E<ge> 8
Windows 8 "fast startup" can prevent virt-sysprep from working.
See L<guestfs(3)/WINDOWS HIBERNATION AND WINDOWS 8 FAST STARTUP>.

View File

@ -0,0 +1,91 @@
From 4c926d7a4b2dc5ac5eaee443f1a901f9e3ad99d4 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2026 12:18:51 +0100
Subject: [PATCH] customize, sysprep: Move firstboot docs from sysprep ->
customize
As a first step towards consolidating all firstboot documentation in
one place, move the "FIRSTBOOT VS SCRIPTS" documentation from
virt-sysprep(1) to virt-customize(1). This section will later be
reworked and expanded, but in this commit it's just a straight move.
(cherry picked from commit 0a148a87541ed5f5b934103e2a1bc7f701d89833)
---
customize/virt-customize.pod | 26 ++++++++++++++++++++++++++
sysprep/virt-sysprep.pod | 26 --------------------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod
index 9fee64ebc..e72e35fac 100644
--- a/customize/virt-customize.pod
+++ b/customize/virt-customize.pod
@@ -240,6 +240,32 @@ Enable tracing of libguestfs API calls.
__CUSTOMIZE_OPTIONS__
+=head1 FIRSTBOOT
+
+The two options I<--firstboot> and I<--script> both supply shell
+scripts that are run against the guest. However these two options are
+significantly different.
+
+I<--firstboot script> uploads the file C<script> into the guest
+and arranges that it will run, in the guest, when the guest is
+next booted. (The script will only run once, at the "first boot").
+
+I<--script script> runs the shell C<script> I<on the host>, with its
+current directory inside the guest filesystem.
+
+If you needed, for example, to C<yum install> new packages, then you
+I<must not> use I<--script> for this, since that would (a) run the
+C<yum> command on the host and (b) wouldn't have access to the same
+resources (repositories, keys, etc.) as the guest. Any command that
+needs to run on the guest I<must> be run via I<--firstboot>.
+
+On the other hand if you need to make adjustments to the guest
+filesystem (eg. copying in files), then I<--script> is ideal since (a)
+it has access to the host filesystem and (b) you will get immediate
+feedback on errors.
+
+Either or both options can be used multiple times on the command line.
+
=head1 SELINUX
For guests which make use of SELinux, special handling for them might
diff --git a/sysprep/virt-sysprep.pod b/sysprep/virt-sysprep.pod
index 4f552b385..4e91a462d 100644
--- a/sysprep/virt-sysprep.pod
+++ b/sysprep/virt-sysprep.pod
@@ -310,32 +310,6 @@ is given.
__OPERATIONS__
-=head1 FIRSTBOOT VS SCRIPT
-
-The two options I<--firstboot> and I<--script> both supply shell
-scripts that are run against the guest. However these two options are
-significantly different.
-
-I<--firstboot script> uploads the file C<script> into the guest
-and arranges that it will run, in the guest, when the guest is
-next booted. (The script will only run once, at the "first boot").
-
-I<--script script> runs the shell C<script> I<on the host>, with its
-current directory inside the guest filesystem.
-
-If you needed, for example, to C<yum install> new packages, then you
-I<must not> use I<--script> for this, since that would (a) run the
-C<yum> command on the host and (b) wouldn't have access to the same
-resources (repositories, keys, etc.) as the guest. Any command that
-needs to run on the guest I<must> be run via I<--firstboot>.
-
-On the other hand if you need to make adjustments to the guest
-filesystem (eg. copying in files), then I<--script> is ideal since (a)
-it has access to the host filesystem and (b) you will get immediate
-feedback on errors.
-
-Either or both options can be used multiple times on the command line.
-
=head1 SECURITY
Virtual machines that employ full disk encryption I<internally to the

View File

@ -0,0 +1,255 @@
From a199dd52457658337511b568d8c1b3cbbf134fcb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 5 May 2026 12:33:14 +0100
Subject: [PATCH] builder, customize: Combine and rework firstboot
documentation
Move the firstboot documentation to virt-customize(1)/FIRSTBOOT, and
combine it with the existing documentation, and rework it.
Update common submodule:
Richard W.M. Jones (1):
mlcustomize: Update generated files
(cherry picked from commit 5a3e8dc37cdb0efd2cbe0901108ac3f9197509f8)
---
builder/virt-builder.pod | 66 ------------------------------------
common | 2 +-
customize/virt-customize.pod | 64 +++++++++++++++++++++++++++++++---
3 files changed, 60 insertions(+), 72 deletions(-)
diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
index fcffecbee..b4db0cbb5 100644
--- a/builder/virt-builder.pod
+++ b/builder/virt-builder.pod
@@ -838,72 +838,6 @@ In any case, the F<~USER/.ssh> directory and the
F<~USER/.ssh/authorized_keys> file will be created if not existing
already.
-=head2 FIRST BOOT SCRIPTS
-
-The I<--firstboot> and I<--firstboot-command> options allow you to
-execute commands at the first boot of the guest. To do so, an init
-script for the guest init system is installed, which takes care of
-running all the added scripts and commands.
-
-Supported operating systems are:
-
-=over 4
-
-=item Linux
-
-Init systems supported are: systemd, System-V init (known also as sysvinit),
-and Upstart (using the System-V scripts).
-
-Note that usually init scripts run as root, but with a more limited
-environment than what could be available from a normal shell:
-for example, C<$HOME> may be unset or empty.
-
-The output of the first boot scripts is available in the guest as
-F<~root/virt-sysprep-firstboot.log>.
-
-=item Windows
-
-F<rhsrvany.exe>, available from sources at
-L<https://github.com/rwmjones/rhsrvany>, or F<pvvxsvc.exe>, available
-with SUSE VMDP is installed to run the
-first boot scripts. It is required, and the setup of first boot
-scripts will fail if it is not present.
-
-F<rhsrvany.exe> or F<pvvxsvc.exe> is copied from the location pointed to by the
-C<VIRT_TOOLS_DATA_DIR> environment variable; if not set, a compiled-in
-default will be used (something like F</usr/share/virt-tools>).
-
-On Windows guests, firstboot scripts are executed by a dedicated
-C<firstboot.bat> script which manages the execution flow. It monitors
-the exit code of each firstboot script:
-
-=over 4
-
-=item * B<250>
-
-The script indicates that a system reboot is not required at
-this stage. The C<firstboot.bat> script will continue
-immediately to the next script in the sequence without
-initiating a shutdown.
-
-=item * B<249>
-
-The script is treated as a failure. The C<firstboot.bat> script
-stops execution, and the system will attempt to run this script
-again on the next boot.
-
-=item * B<Any other code>
-
-The script is considered a success. The C<firstboot.bat> script
-proceeds to the next script in the sequence.
-
-=back
-
-The output of the first boot scripts is available in the guest as
-F<C:\Program Files\Guestfs\Firstboot\log.txt>.
-
-=back
-
=head2 INSTALLATION PROCESS
When you invoke virt-builder, installation proceeds as follows:
Submodule common 228449739..dd34aebb4:
diff --git a/common/mlcustomize/customize-options.pod b/common/mlcustomize/customize-options.pod
index c8de3953c..95767cc73 100644
--- a/common/mlcustomize/customize-options.pod
+++ b/common/mlcustomize/customize-options.pod
@@ -161,10 +161,7 @@ conveniently wraps the command up in a single line script for you.
You can have multiple I<--firstboot> options. They run in the same
order that they appear on the command line.
-Please take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more
-information and caveats about the first boot scripts.
-
-See also I<--run>.
+See also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.
=item B<--firstboot-command> 'CMD+ARGS'
@@ -174,10 +171,7 @@ boots up (as root, late in the boot process).
You can have multiple I<--firstboot> options. They run in the same
order that they appear on the command line.
-Please take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more
-information and caveats about the first boot scripts.
-
-See also I<--run>.
+See also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.
=item B<--firstboot-install> PKG,PKG..
diff --git a/common/mlcustomize/customize_cmdline.ml b/common/mlcustomize/customize_cmdline.ml
index 786f4ee49..b8eda519d 100644
--- a/common/mlcustomize/customize_cmdline.ml
+++ b/common/mlcustomize/customize_cmdline.ml
@@ -252,13 +252,13 @@ let rec argspec ?(v2v = false) () =
Getopt.String (s_"SCRIPT", fun s -> List.push_front (`FirstbootScript s) ops),
s_"Run script at first guest boot"
),
- Some "SCRIPT", "Install C<SCRIPT> inside the guest, so that when the guest first boots\nup, the script runs (as root, late in the boot process).\n\nThe script is automatically chmod +x after installation in the guest.\n\nThe alternative version I<--firstboot-command> is the same, but it\nconveniently wraps the command up in a single line script for you.\n\nYou can have multiple I<--firstboot> options. They run in the same\norder that they appear on the command line.\n\nPlease take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more\ninformation and caveats about the first boot scripts.\n\nSee also I<--run>.", false;
+ Some "SCRIPT", "Install C<SCRIPT> inside the guest, so that when the guest first boots\nup, the script runs (as root, late in the boot process).\n\nThe script is automatically chmod +x after installation in the guest.\n\nThe alternative version I<--firstboot-command> is the same, but it\nconveniently wraps the command up in a single line script for you.\n\nYou can have multiple I<--firstboot> options. They run in the same\norder that they appear on the command line.\n\nSee also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.", false;
(
[ L"firstboot-command" ],
Getopt.String (s_"'CMD+ARGS'", fun s -> List.push_front (`FirstbootCommand s) ops),
s_"Run command at first guest boot"
),
- Some "'CMD+ARGS'", "Run command (and arguments) inside the guest when the guest first\nboots up (as root, late in the boot process).\n\nYou can have multiple I<--firstboot> options. They run in the same\norder that they appear on the command line.\n\nPlease take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more\ninformation and caveats about the first boot scripts.\n\nSee also I<--run>.", false;
+ Some "'CMD+ARGS'", "Run command (and arguments) inside the guest when the guest first\nboots up (as root, late in the boot process).\n\nYou can have multiple I<--firstboot> options. They run in the same\norder that they appear on the command line.\n\nSee also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.", false;
(
[ L"firstboot-install" ],
Getopt.String (
diff --git a/common/mlcustomize/v2v-customize-options.pod b/common/mlcustomize/v2v-customize-options.pod
index f02f05dac..6252ffe98 100644
--- a/common/mlcustomize/v2v-customize-options.pod
+++ b/common/mlcustomize/v2v-customize-options.pod
@@ -161,10 +161,7 @@ conveniently wraps the command up in a single line script for you.
You can have multiple I<--firstboot> options. They run in the same
order that they appear on the command line.
-Please take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more
-information and caveats about the first boot scripts.
-
-See also I<--run>.
+See also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.
=item B<--firstboot-command> 'CMD+ARGS'
@@ -174,10 +171,7 @@ boots up (as root, late in the boot process).
You can have multiple I<--firstboot> options. They run in the same
order that they appear on the command line.
-Please take a look at L<virt-builder(1)/FIRST BOOT SCRIPTS> for more
-information and caveats about the first boot scripts.
-
-See also I<--run>.
+See also: L<virt-customize(1)/FIRSTBOOT>, I<--run>.
=item B<--firstboot-install> PKG,PKG..
diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod
index e72e35fac..71b13e613 100644
--- a/customize/virt-customize.pod
+++ b/customize/virt-customize.pod
@@ -242,16 +242,70 @@ __CUSTOMIZE_OPTIONS__
=head1 FIRSTBOOT
+The I<--firstboot> and I<--firstboot-command> options allow you to
+execute commands at the first boot of the guest. To do so, an init
+script for the guest init system is installed, which takes care of
+running all the added scripts and commands.
+
+=head2 Log file
+
+On Linux, output from the scripts is written to
+S<F<~root/virt-sysprep-firstboot.log>> inside the guest.
+
+On Windows, output is written to
+S<F<C:\Program Files\Guestfs\Firstboot\log.txt>> inside the guest.
+
+=head2 Windows firstboot batch file exit codes
+
+On Windows guests (only) the exit code of batch files controls the
+execution flow and whether Windows will reboot between each script:
+
+=over 4
+
+=item * 249
+
+The batch file is treated as a failure. The batch file will be run
+again on next reboot. (Be careful that batch files do not
+continuously give this exit code, otherwise Windows will boot loop.)
+
+=item * 250
+
+The script indicates that a system reboot is not required at this
+stage. The next script in the sequence will run without initiating a
+reboot.
+
+=item * Any other code
+
+This script is considered successful. Windows will reboot and run the
+next script.
+
+=back
+
+=head2 Auxiliary tools
+
+On Windows guests, F<rhsrvany.exe>, available from sources at
+L<https://github.com/rwmjones/rhsrvany>, or F<pvvxsvc.exe>, available
+with SUSE VMDP, is installed to run the first boot scripts. One of
+these is required, and the setup of first boot scripts will fail if
+not present.
+
+F<rhsrvany.exe> or F<pvvxsvc.exe> is copied from the location pointed
+to by the C<VIRT_TOOLS_DATA_DIR> environment variable; if not set, a
+compiled-in default will be used (something like
+F</usr/share/virt-tools>).
+
+=head2 I<--firstboot> vs I<--script>
+
The two options I<--firstboot> and I<--script> both supply shell
scripts that are run against the guest. However these two options are
significantly different.
-I<--firstboot script> uploads the file C<script> into the guest
-and arranges that it will run, in the guest, when the guest is
-next booted. (The script will only run once, at the "first boot").
+I<--firstboot script> uploads the file C<script> into the guest and
+arranges that it will run, in the guest, when the guest is next
+booted.
-I<--script script> runs the shell C<script> I<on the host>, with its
-current directory inside the guest filesystem.
+I<--script> runs the shell script I<on the host>, with its current
+directory inside the guest filesystem.
If you needed, for example, to C<yum install> new packages, then you
I<must not> use I<--script> for this, since that would (a) run the

View File

@ -0,0 +1,31 @@
From 8f1b3b6d6c1c24d1cdaeef5bdc22238c709f48ee Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 7 May 2026 10:25:04 +0100
Subject: [PATCH] customize: Document location of Windows sentinel file
Link: https://github.com/libguestfs/libguestfs-common/commit/cb0e19b754b060bf9e783cbd1510c9719dfc9730
(cherry picked from commit 592f11c86c07b9a491d78ca07ba10b5cbeca2926)
---
customize/virt-customize.pod | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/customize/virt-customize.pod b/customize/virt-customize.pod
index 71b13e613..c21192d1b 100644
--- a/customize/virt-customize.pod
+++ b/customize/virt-customize.pod
@@ -281,6 +281,15 @@ next script.
=back
+=head2 Windows sentinel file
+
+On Windows guests (only) a sentinel file is written into the guest
+once all firstboot scripts have finished running. You can use this to
+detect if the Windows guest is ready (eg. has finished a
+L<virt-v2v(1)> conversion). The default location for this file is:
+
+ C:\Program Files\Guestfs\Firstboot\complete
+
=head2 Auxiliary tools
On Windows guests, F<rhsrvany.exe>, available from sources at

View File

@ -1,4 +1,4 @@
From 1107ededf2cad9982befb4d4b90353117b29d474 Mon Sep 17 00:00:00 2001
From 2f82e84767555a59108d2467970e13c93e0a5b4b 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
@ -11,7 +11,7 @@ edits.
1 file changed, 1 insertion(+)
diff --git a/test-data/phony-guests/make-windows-img.sh b/test-data/phony-guests/make-windows-img.sh
index 16debd129..1c13ddac3 100755
index e72013c3d..ac661f180 100755
--- a/test-data/phony-guests/make-windows-img.sh
+++ b/test-data/phony-guests/make-windows-img.sh
@@ -37,6 +37,7 @@ fi
@ -19,6 +19,6 @@ index 16debd129..1c13ddac3 100755
# Create a disk image.
guestfish <<EOF
+set-program virt-testing
sparse windows.img-t 512M
sparse windows.img-t 2G
run

View File

@ -1,4 +1,4 @@
From 517a2ad502fa3773db50e883c0bece69b03b31ca Mon Sep 17 00:00:00 2001
From b6a3ccc92752715293a801a025803a4ae52ec00b Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Mon, 21 Nov 2022 13:03:22 +0000
Subject: [PATCH] RHEL: builder: Disable opensuse repository

View File

@ -1,254 +0,0 @@
From 1cb20d561c6b2e93980ba9c7c7269b32f6d768eb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Thu, 16 May 2024 12:49:24 +0100
Subject: [PATCH] customize: Implement --inject-blnsvr operation
Also updates the common submodule with the generated changes from
libguestfs, and the implementation of Inject_virtio_win.inject_blnsvr.
(cherry picked from commit 80d258baa49214c8e59b91d6085595c9b989fc0d)
---
common | 2 +-
customize/customize_run.ml | 13 +++++++++++--
2 files changed, 12 insertions(+), 3 deletions(-)
Submodule common 7cbb3ba35...a78839676:
diff --git a/common/mlcustomize/customize-options.pod b/common/mlcustomize/customize-options.pod
index ff93630d8..b2ac57526 100644
--- a/common/mlcustomize/customize-options.pod
+++ b/common/mlcustomize/customize-options.pod
@@ -193,6 +193,18 @@ L<virt-builder(1)/INSTALLING PACKAGES>.
Set the hostname of the guest to C<HOSTNAME>. You can use a
dotted hostname.domainname (FQDN) if you want.
+=item B<--inject-blnsvr> METHOD
+
+Inject the Balloon Server (F<blnsvr.exe>) into a Windows guest.
+This operation also injects a firstboot script so that the Balloon
+Server is installed when the guest boots.
+
+The parameter is the same as used by the I<--inject-virtio-win> operation.
+
+Note that to do a full conversion of a Windows guest from a
+foreign hypervisor like VMware (which involves many other operations)
+you should use the L<virt-v2v(1)> tool instead of this.
+
=item B<--inject-qemu-ga> METHOD
Inject the QEMU Guest Agent into a Windows guest. The guest
diff --git a/common/mlcustomize/customize-synopsis.pod b/common/mlcustomize/customize-synopsis.pod
index bb0ce1255..957de8cf2 100644
--- a/common/mlcustomize/customize-synopsis.pod
+++ b/common/mlcustomize/customize-synopsis.pod
@@ -3,16 +3,16 @@
[--copy SOURCE:DEST] [--copy-in LOCALPATH:REMOTEDIR]
[--delete PATH] [--edit FILE:EXPR] [--firstboot SCRIPT]
[--firstboot-command 'CMD+ARGS'] [--firstboot-install PKG,PKG..]
- [--hostname HOSTNAME] [--inject-qemu-ga METHOD]
- [--inject-virtio-win METHOD] [--install PKG,PKG..]
- [--link TARGET:LINK[:LINK..]] [--mkdir DIR] [--move SOURCE:DEST]
- [--password USER:SELECTOR] [--root-password SELECTOR]
- [--run SCRIPT] [--run-command 'CMD+ARGS'] [--scrub FILE]
- [--sm-attach SELECTOR] [--sm-register] [--sm-remove]
- [--sm-unregister] [--ssh-inject USER[:SELECTOR]]
- [--tar-in TARFILE:REMOTEDIR] [--timezone TIMEZONE] [--touch FILE]
- [--truncate FILE] [--truncate-recursive PATH]
- [--uninstall PKG,PKG..] [--update] [--upload FILE:DEST]
- [--write FILE:CONTENT] [--no-logfile]
+ [--hostname HOSTNAME] [--inject-blnsvr METHOD]
+ [--inject-qemu-ga METHOD] [--inject-virtio-win METHOD]
+ [--install PKG,PKG..] [--link TARGET:LINK[:LINK..]] [--mkdir DIR]
+ [--move SOURCE:DEST] [--password USER:SELECTOR]
+ [--root-password SELECTOR] [--run SCRIPT]
+ [--run-command 'CMD+ARGS'] [--scrub FILE] [--sm-attach SELECTOR]
+ [--sm-register] [--sm-remove] [--sm-unregister]
+ [--ssh-inject USER[:SELECTOR]] [--tar-in TARFILE:REMOTEDIR]
+ [--timezone TIMEZONE] [--touch FILE] [--truncate FILE]
+ [--truncate-recursive PATH] [--uninstall PKG,PKG..] [--update]
+ [--upload FILE:DEST] [--write FILE:CONTENT] [--no-logfile]
[--password-crypto md5|sha256|sha512] [--no-selinux-relabel]
[--selinux-relabel] [--sm-credentials SELECTOR]
diff --git a/common/mlcustomize/customize_cmdline.ml b/common/mlcustomize/customize_cmdline.ml
index 48ee33445..c4d6a77d5 100644
--- a/common/mlcustomize/customize_cmdline.ml
+++ b/common/mlcustomize/customize_cmdline.ml
@@ -61,6 +61,8 @@ and op = [
(* --firstboot-install PKG,PKG.. *)
| `Hostname of string
(* --hostname HOSTNAME *)
+ | `InjectBalloonServer of string
+ (* --inject-blnsvr METHOD *)
| `InjectQemuGA of string
(* --inject-qemu-ga METHOD *)
| `InjectVirtioWin of string
@@ -286,6 +288,12 @@ let rec argspec () =
s_"Set the hostname"
),
Some "HOSTNAME", "Set the hostname of the guest to C<HOSTNAME>. You can use a\ndotted hostname.domainname (FQDN) if you want.";
+ (
+ [ L"inject-blnsvr" ],
+ Getopt.String (s_"METHOD", fun s -> List.push_front (`InjectBalloonServer s) ops),
+ s_"Inject the Balloon Server into a Windows guest"
+ ),
+ Some "METHOD", "Inject the Balloon Server (F<blnsvr.exe>) into a Windows guest.\nThis operation also injects a firstboot script so that the Balloon\nServer is installed when the guest boots.\n\nThe parameter is the same as used by the I<--inject-virtio-win> operation.\n\nNote that to do a full conversion of a Windows guest from a\nforeign hypervisor like VMware (which involves many other operations)\nyou should use the L<virt-v2v(1)> tool instead of this.";
(
[ L"inject-qemu-ga" ],
Getopt.String (s_"METHOD", fun s -> List.push_front (`InjectQemuGA s) ops),
diff --git a/common/mlcustomize/customize_cmdline.mli b/common/mlcustomize/customize_cmdline.mli
index 51a156eae..ee62961a1 100644
--- a/common/mlcustomize/customize_cmdline.mli
+++ b/common/mlcustomize/customize_cmdline.mli
@@ -53,6 +53,8 @@ and op = [
(* --firstboot-install PKG,PKG.. *)
| `Hostname of string
(* --hostname HOSTNAME *)
+ | `InjectBalloonServer of string
+ (* --inject-blnsvr METHOD *)
| `InjectQemuGA of string
(* --inject-qemu-ga METHOD *)
| `InjectVirtioWin of string
diff --git a/common/mlcustomize/inject_virtio_win.ml b/common/mlcustomize/inject_virtio_win.ml
index 0a4b8dac0..afec1e456 100644
--- a/common/mlcustomize/inject_virtio_win.ml
+++ b/common/mlcustomize/inject_virtio_win.ml
@@ -24,6 +24,8 @@ open Common_gettext.Gettext
open Regedit
+let re_blnsvr = PCRE.compile ~caseless:true "\\bblnsvr\\.exe$"
+
type t = {
g : Guestfs.guestfs; (** guestfs handle *)
@@ -274,6 +276,25 @@ and inject_qemu_ga ({ g; root } as t) =
configure_qemu_ga t tempdir_win msi_files;
msi_files <> [] (* return true if we found some qemu-ga MSI files *)
+and inject_blnsvr ({ g; root } as t) =
+ (* Copy the files to the guest. *)
+ let dir, dir_win = Firstboot.firstboot_dir g root in
+ let dir_win = Option.value dir_win ~default:dir in
+ let tempdir = sprintf "%s/Temp" dir in
+ let tempdir_win = sprintf "%s\\Temp" dir_win in
+ g#mkdir_p tempdir;
+
+ let files = copy_blnsvr t tempdir in
+ match files with
+ | [] -> false (* Didn't find or install anything. *)
+
+ (* We usually find blnsvr.exe in two locations (drivers/by-os and
+ * drivers/by-driver). Pick the first.
+ *)
+ | blnsvr :: _ ->
+ configure_blnsvr t tempdir_win blnsvr;
+ true
+
and add_guestor_to_registry t ((g, root) as reg) drv_name drv_pciid =
let ddb_node = g#hivex_node_get_child root "DriverDatabase" in
@@ -358,6 +379,11 @@ and copy_qemu_ga t tempdir =
(fun () ->
error (f_"root directory / is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way. Please report this as a bug with a full debug log."))
+and copy_blnsvr t tempdir =
+ copy_from_virtio_win t "/" tempdir (virtio_iso_path_matches_blnsvr t)
+ (fun () ->
+ error (f_"root directory / is missing from the virtio-win directory or ISO.\n\nThis should not happen and may indicate that virtio-win or virt-v2v is broken in some way. Please report this as a bug with a full debug log."))
+
(* Copy all files from virtio_win directory/ISO located in [srcdir]
* subdirectory and all its subdirectories to the [destdir]. The directory
* hierarchy is not preserved, meaning all files will be directly in [destdir].
@@ -452,10 +478,7 @@ and virtio_iso_path_matches_guest_os t path =
* "./drivers/amd64/Win2012R2/netkvm.sys".
* Note we check lowercase paths.
*)
- let pathelem elem =
- String.find lc_path ("/" ^ elem ^ "/") >= 0 ||
- String.is_prefix lc_path (elem ^ "/")
- in
+ let pathelem elem = String.find lc_path ("/" ^ elem ^ "/") >= 0 in
let p_arch =
if pathelem "x86" || pathelem "i386" then "i386"
else if pathelem "amd64" then "x86_64"
@@ -499,11 +522,7 @@ and virtio_iso_path_matches_guest_os t path =
else
raise Not_found in
- let p_sriov = pathelem "sriov" in
-
- arch = p_arch &&
- not p_sriov && (* always ignored, see RHEL-56383 *)
- os_major = p_os_major && os_minor = p_os_minor &&
+ arch = p_arch && os_major = p_os_major && os_minor = p_os_minor &&
match_os_variant os_variant &&
match_osinfo osinfo
@@ -527,6 +546,10 @@ and virtio_iso_path_matches_qemu_ga t path =
| ("x86_64", "rhev-qga64.msi") -> true
| _ -> false
+(* Find blnsvr for the current Windows version. *)
+and virtio_iso_path_matches_blnsvr t path =
+ virtio_iso_path_matches_guest_os t path && PCRE.matches re_blnsvr path
+
(* Look up in libosinfo for the OS, and copy all the locally
* available files specified as drivers for that OS to the [destdir].
*
@@ -591,3 +614,10 @@ and configure_qemu_ga t tempdir_win files =
) files;
Firstboot.add_firstboot_powershell t.g t.root "install-qemu-ga" !script
+
+and configure_blnsvr t tempdir_win blnsvr =
+ let cmd = sprintf "\
+ @echo off\n\
+ echo Installing %s\n\
+ \"%s\\%s\" -i\n" blnsvr tempdir_win blnsvr in
+ Firstboot.add_firstboot_script t.g t.root "install-blnsvr" cmd
diff --git a/common/mlcustomize/inject_virtio_win.mli b/common/mlcustomize/inject_virtio_win.mli
index d14f04973..d273c4dd3 100644
--- a/common/mlcustomize/inject_virtio_win.mli
+++ b/common/mlcustomize/inject_virtio_win.mli
@@ -93,3 +93,11 @@ val inject_qemu_ga : t -> bool
the MSI(s).
Returns [true] iff we were able to inject qemu-ga. *)
+
+val inject_blnsvr : t -> bool
+(** Inject the Balloon Server ([blnsvr.exe]) into a Windows guest.
+
+ A firstboot script is also injected which should install
+ the server by running [blnsvr -i].
+
+ Returns [true] iff we were able to inject the Balloon Server. *)
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 1314d6e30..1d7c13eaf 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -113,8 +113,8 @@ let run (g : G.guestfs) root (ops : ops) =
Hashtbl.replace passwords user pw
in
- (* Helper function to convert --inject-qemu-ga/--inject-virtio-win
- * method parameter into a virtio-win handle.
+ (* Helper function to convert --inject-blnsvr/--inject-qemu-ga/
+ * --inject-virtio-win method parameter into a virtio-win handle.
*)
let get_virtio_win_handle op meth =
if g#inspect_get_type root <> "windows" then (
@@ -216,6 +216,15 @@ let run (g : G.guestfs) root (ops : ops) =
if not (Hostname.set_hostname g root hostname) then
warning (f_"hostname could not be set for this type of guest")
+ | `InjectBalloonServer meth ->
+ (match get_virtio_win_handle "--inject-blnsvr" meth with
+ | None -> ()
+ | Some t ->
+ if not (Inject_virtio_win.inject_blnsvr t) then
+ warning (f_"--inject-blnsvr: blnsvr.exe not found in \
+ virtio-win source that you specified")
+ )
+
| `InjectQemuGA meth ->
(match get_virtio_win_handle "--inject-qemu-ga" meth with
| None -> ()

View File

@ -1,33 +0,0 @@
From 9cdb27fb0fde8b2eb57453480c4fed4746414aeb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 22 Oct 2024 11:01:25 +0100
Subject: [PATCH] build: Add new dependency on json-c
This will eventually replace Jansson for all JSON parsing. However
this commit simply introduces the new dependency in the configure
script and documents it.
I chose json-c 0.14 as the baseline since that is the version in RHEL 9.
Probably earlier versions would work.
(cherry picked from libguestfs commit 53872a0a1a267040677572c30b68bd1e8b62ebe3)
(cherry picked from commit 0d7fe8a0b0b429152ea02fc7a7e4f5a1b0eba590)
---
m4/guestfs-libraries.m4 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 32f93afda..b76511982 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -167,6 +167,9 @@ LIBS="$old_LIBS"
dnl Check for Jansson JSON library (required).
PKG_CHECK_MODULES([JANSSON], [jansson >= 2.7])
+dnl Check for JSON-C library (required).
+PKG_CHECK_MODULES([JSON_C], [json-c >= 0.14])
+
dnl Check for libosinfo (mandatory)
PKG_CHECK_MODULES([LIBOSINFO], [libosinfo-1.0])

View File

@ -1,267 +0,0 @@
From 02a911960b5916df93bf896afc94c8d250797f17 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 22 Oct 2024 11:07:01 +0100
Subject: [PATCH] builder: Replace jansson with json-c
This pulls in the following common module commit which ports the
JSON_parser module from jansson to json-c:
Richard W.M. Jones (1):
mltools: Replace jansson with json-c
(cherry picked from commit 12997768d231b80dc219a518c287ecf10c83ff0e)
---
builder/Makefile.am | 2 +-
common | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/builder/Makefile.am b/builder/Makefile.am
index b474f0c9d..0761eff4c 100644
--- a/builder/Makefile.am
+++ b/builder/Makefile.am
@@ -206,7 +206,7 @@ OCAMLCLIBS = \
$(LIBLZMA_LIBS) \
$(LIBXML2_LIBS) \
$(LIBOSINFO_LIBS) \
- $(JANSSON_LIBS) \
+ $(JSON_C_LIBS) \
$(LIBINTL) \
-lgnu
Submodule common a78839676..766384a45:
diff --git a/common/mltools/JSON_parser-c.c b/common/mltools/JSON_parser-c.c
index bf38dd1bf..fb67b4632 100644
--- a/common/mltools/JSON_parser-c.c
+++ b/common/mltools/JSON_parser-c.c
@@ -23,7 +23,7 @@
#include <caml/memory.h>
#include <caml/mlvalues.h>
-#include <jansson.h>
+#include <json.h>
#include <stdio.h>
#include <string.h>
@@ -40,7 +40,7 @@ value virt_builder_json_parser_tree_parse (value stringv);
value virt_builder_json_parser_tree_parse_file (value stringv);
static value
-convert_json_t (json_t *val, int level)
+convert_json_t (json_object *val, int level)
{
CAMLparam0 ();
CAMLlocal5 (rv, v, tv, sv, consv);
@@ -48,9 +48,11 @@ convert_json_t (json_t *val, int level)
if (level > 20)
caml_invalid_argument ("too many levels of object/array nesting");
- if (json_is_object (val)) {
+ switch (json_object_get_type (val)) {
+ case json_type_object: {
+ struct json_object_iterator it, itend;
const char *key;
- json_t *jvalue;
+ json_object *jvalue;
rv = caml_alloc (1, JSON_DICT_TAG);
v = Val_int (0);
@@ -60,29 +62,39 @@ convert_json_t (json_t *val, int level)
* matter (eg. simplestreams which incorrectly uses a dict when it
* really should use an array).
*/
- json_object_foreach (val, key, jvalue) {
+ it = json_object_iter_begin (val);
+ itend = json_object_iter_end (val);
+ while (!json_object_iter_equal (&it, &itend)) {
+ key = json_object_iter_peek_name (&it);
tv = caml_alloc_tuple (2);
sv = caml_copy_string (key);
Store_field (tv, 0, sv);
+
+ jvalue = json_object_iter_peek_value (&it);
sv = convert_json_t (jvalue, level + 1);
Store_field (tv, 1, sv);
+
consv = caml_alloc (2, 0);
Store_field (consv, 1, v);
Store_field (consv, 0, tv);
v = consv;
+
+ json_object_iter_next (&it);
}
Store_field (rv, 0, v);
+ break;
}
- else if (json_is_array (val)) {
- const size_t len = json_array_size (val);
+
+ case json_type_array: {
+ const size_t len = json_object_array_length (val);
size_t i;
- json_t *jvalue;
+ json_object *jvalue;
rv = caml_alloc (1, JSON_LIST_TAG);
v = Val_int (0);
for (i = 0; i < len; ++i) {
/* Note we have to create the OCaml list backwards. */
- jvalue = json_array_get (val, len-i-1);
+ jvalue = json_object_array_get_idx (val, len-i-1);
tv = convert_json_t (jvalue, level + 1);
consv = caml_alloc (2, 0);
Store_field (consv, 1, v);
@@ -90,32 +102,36 @@ convert_json_t (json_t *val, int level)
v = consv;
}
Store_field (rv, 0, v);
+ break;
}
- else if (json_is_string (val)) {
+
+ case json_type_string:
rv = caml_alloc (1, JSON_STRING_TAG);
- v = caml_copy_string (json_string_value (val));
+ v = caml_copy_string (json_object_get_string (val));
Store_field (rv, 0, v);
- }
- else if (json_is_real (val)) {
+ break;
+
+ case json_type_double:
rv = caml_alloc (1, JSON_FLOAT_TAG);
- v = caml_copy_double (json_real_value (val));
+ v = caml_copy_double (json_object_get_double (val));
Store_field (rv, 0, v);
- }
- else if (json_is_integer (val)) {
+ break;
+
+ case json_type_int:
rv = caml_alloc (1, JSON_INT_TAG);
- v = caml_copy_int64 (json_integer_value (val));
+ v = caml_copy_int64 (json_object_get_int64 (val));
Store_field (rv, 0, v);
- }
- else if (json_is_true (val)) {
+ break;
+
+ case json_type_boolean:
rv = caml_alloc (1, JSON_BOOL_TAG);
- Store_field (rv, 0, Val_true);
- }
- else if (json_is_false (val)) {
- rv = caml_alloc (1, JSON_BOOL_TAG);
- Store_field (rv, 0, Val_false);
- }
- else
+ Store_field (rv, 0, json_object_get_boolean (val) ? Val_true : Val_false);
+ break;
+
+ case json_type_null:
rv = JSON_NULL;
+ break;
+ }
CAMLreturn (rv);
}
@@ -125,45 +141,28 @@ virt_builder_json_parser_tree_parse (value stringv)
{
CAMLparam1 (stringv);
CAMLlocal1 (rv);
- json_t *tree;
- json_error_t err;
+ json_object *tree = NULL;
+ json_tokener *tok = NULL;
+ enum json_tokener_error err;
- tree = json_loads (String_val (stringv), JSON_DECODE_ANY, &err);
- if (tree == NULL) {
- char buf[256 + JSON_ERROR_TEXT_LENGTH];
- if (strlen (err.text) > 0)
- snprintf (buf, sizeof buf, "JSON parse error: %s", err.text);
- else
- snprintf (buf, sizeof buf, "unknown JSON parse error");
+ tok = json_tokener_new ();
+ json_tokener_set_flags (tok,
+ JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8);
+ tree = json_tokener_parse_ex (tok,
+ String_val (stringv),
+ caml_string_length (stringv));
+ err = json_tokener_get_error (tok);
+ if (err != json_tokener_success) {
+ char buf[256];
+ snprintf (buf, sizeof buf, "JSON parse error: %s",
+ json_tokener_error_desc (err));
+ json_tokener_free (tok);
caml_invalid_argument (buf);
}
+ json_tokener_free (tok);
rv = convert_json_t (tree, 1);
- json_decref (tree);
-
- CAMLreturn (rv);
-}
-
-value
-virt_builder_json_parser_tree_parse_file (value filev)
-{
- CAMLparam1 (filev);
- CAMLlocal1 (rv);
- json_t *tree;
- json_error_t err;
-
- tree = json_load_file (String_val (filev), JSON_DECODE_ANY, &err);
- if (tree == NULL) {
- char buf[1024 + JSON_ERROR_TEXT_LENGTH];
- if (strlen (err.text) > 0)
- snprintf (buf, sizeof buf, "%s: JSON parse error: %s", String_val (filev), err.text);
- else
- snprintf (buf, sizeof buf, "%s: unknown JSON parse error", String_val (filev));
- caml_invalid_argument (buf);
- }
-
- rv = convert_json_t (tree, 1);
- json_decref (tree);
+ json_object_put (tree);
CAMLreturn (rv);
}
diff --git a/common/mltools/JSON_parser.ml b/common/mltools/JSON_parser.ml
index 933057277..8bc35abdc 100644
--- a/common/mltools/JSON_parser.ml
+++ b/common/mltools/JSON_parser.ml
@@ -21,7 +21,10 @@ open Tools_utils
open Common_gettext.Gettext
external json_parser_tree_parse : string -> JSON.json_t = "virt_builder_json_parser_tree_parse"
-external json_parser_tree_parse_file : string -> JSON.json_t = "virt_builder_json_parser_tree_parse_file"
+
+let json_parser_tree_parse_file filename =
+ let content = read_whole_file filename in
+ json_parser_tree_parse content
let object_find_optional key = function
| JSON.Dict fields ->
diff --git a/common/mltools/Makefile.am b/common/mltools/Makefile.am
index f510a6747..684c26946 100644
--- a/common/mltools/Makefile.am
+++ b/common/mltools/Makefile.am
@@ -116,7 +116,7 @@ libmltools_a_CFLAGS = \
$(LIBVIRT_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(LIBGUESTFS_CFLAGS) \
- $(JANSSON_CFLAGS) \
+ $(JSON_C_CFLAGS) \
$(LIBOSINFO_CFLAGS) \
-fPIC
@@ -148,7 +148,7 @@ OCAMLCLIBS = \
$(LIBCRYPT_LIBS) \
$(LIBVIRT_LIBS) \
$(LIBXML2_LIBS) \
- $(JANSSON_LIBS) \
+ $(JSON_C_LIBS) \
$(LIBOSINFO_LIBS) \
$(LIBINTL) \
-lgnu

View File

@ -1,27 +0,0 @@
From 5879249a32d50ab746f515abc2679b91f64a2098 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 22 Oct 2024 15:22:18 +0100
Subject: [PATCH] build: Remove Jansson dependency
After previous changes, this library is no longer used. We have
switched to json-c, for better compatibility with libvirt.
(cherry picked from commit e6dcf7e3a7e9170978e57ce6df1b34f92fac5ae3)
---
m4/guestfs-libraries.m4 | 3 ---
1 file changed, 3 deletions(-)
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index b76511982..80f9425f0 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -164,9 +164,6 @@ LIBS="$LIBS $LIBXML2_LIBS"
AC_CHECK_FUNCS([xmlBufferDetach])
LIBS="$old_LIBS"
-dnl Check for Jansson JSON library (required).
-PKG_CHECK_MODULES([JANSSON], [jansson >= 2.7])
-
dnl Check for JSON-C library (required).
PKG_CHECK_MODULES([JSON_C], [json-c >= 0.14])

View File

@ -1,151 +0,0 @@
From 065f95e7afa45bf465e8799baa11c019f9403bd6 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 19 Feb 2025 15:15:30 +0000
Subject: [PATCH] test-data: phony fedora: Add simple static /bin/sh
This is able to do enough to run commands via g#sh and related calls
inside the phony Fedora image.
(cherry picked from commit 4c5854f54e1da0d96807acb1b047bbf34694a0bb)
---
cat/test-virt-ls.sh | 1 +
test-data/phony-guests/fedora.c | 76 +++++++++++++++++++++--
test-data/phony-guests/make-fedora-img.pl | 6 +-
3 files changed, 76 insertions(+), 7 deletions(-)
diff --git a/cat/test-virt-ls.sh b/cat/test-virt-ls.sh
index e98faa42b..577a44860 100755
--- a/cat/test-virt-ls.sh
+++ b/cat/test-virt-ls.sh
@@ -24,6 +24,7 @@ skip_if_skipped
# Read out the test directory using virt-ls.
if [ "$($VG virt-ls --format=raw -a ../test-data/phony-guests/fedora.img /bin)" != "ls
rpm
+sh
test1
test2
test3
diff --git a/test-data/phony-guests/fedora.c b/test-data/phony-guests/fedora.c
index c57fa57cc..df097e9e6 100644
--- a/test-data/phony-guests/fedora.c
+++ b/test-data/phony-guests/fedora.c
@@ -16,13 +16,14 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/* This is "just enough" of a binary to look like RPM and dracut, as
- * far as virt-v2v is concerned.
+/* This is "just enough" of a binary to look like /bin/sh, RPM and
+ * dracut, as far as virt-v2v is concerned.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
/* NB: This is also defined in make-fedora-img.pl */
#define KVER "5.19.0-0.rc1.14.fc37.x86_64"
@@ -34,6 +35,27 @@ get_basename (const char *str)
return ret == NULL ? str : ret + 1;
}
+static void
+add_str (char ***argv, size_t *argc, char *str)
+{
+ (*argc)++;
+ (*argv) = realloc (*argv, *argc * sizeof (char *));
+ (*argv)[*argc-1] = str;
+}
+
+static void
+add_null (char ***argv, size_t *argc)
+{
+ add_str (argv, argc, NULL);
+}
+
+static void
+add (char ***argv, size_t *argc, const char *s, size_t len)
+{
+ char *copy = strndup (s, len);
+ add_str (argv, argc, copy);
+}
+
int
main (int argc, char *argv[])
{
@@ -57,10 +79,54 @@ main (int argc, char *argv[])
strcmp (get_basename (argv[0]), "dracut") == 0) {
// do nothing, pretend to rebuild the initramfs
}
+ else if (argc == 3 &&
+ strcmp (get_basename (argv[0]), "sh") == 0 &&
+ strcmp (argv[1], "-c") == 0) {
+ /* Split the command and execute it. Only handles trivial cases. */
+ char *cmd = argv[2];
+ char **cmdv = NULL;
+ size_t i, cmdvlen = 0, n;
+ const size_t len = strlen (cmd);
+
+ for (i = 0; i < len;) {
+ switch (cmd[i]) {
+ case ' ': case '\t':
+ i++;
+ continue;
+
+ case '"':
+ n = strcspn (&cmd[i+1], "\"");
+ add (&cmdv, &cmdvlen, &cmd[i+1], n);
+ i += n+2;
+ break;
+
+ case '\'':
+ n = strcspn (&cmd[i+1], "'");
+ add (&cmdv, &cmdvlen, &cmd[i+1], n);
+ i += n+2;
+ break;
+
+ default:
+ n = strcspn (&cmd[i], " \t");
+ add (&cmdv, &cmdvlen, &cmd[i], n);
+ i += n;
+ }
+ }
+ add_null (&cmdv, &cmdvlen);
+
+ execvp (cmdv[0], cmdv);
+ perror (cmdv[0]);
+ exit (EXIT_FAILURE);
+ }
else {
- fprintf (stderr, "phony Fedora: unknown command\n");
- exit (1);
+ int i;
+
+ fprintf (stderr, "ERROR: test-data/phony-guests/fedora.c: "
+ "unexpected command:\n");
+ for (i = 0; i < argc; ++i)
+ fprintf (stderr, "argv[%d] = %s\n", i, argv[i]);
+ exit (EXIT_FAILURE);
}
- exit (0);
+ exit (EXIT_SUCCESS);
}
diff --git a/test-data/phony-guests/make-fedora-img.pl b/test-data/phony-guests/make-fedora-img.pl
index 0de506324..fef8ce032 100755
--- a/test-data/phony-guests/make-fedora-img.pl
+++ b/test-data/phony-guests/make-fedora-img.pl
@@ -369,8 +369,10 @@ $g->ln_s ('/bin/test1', '/bin/test5');
$g->mkfifo (0777, '/bin/test6');
$g->mknod (0777, 10, 10, '/bin/test7');
-# Virt-v2v needs an RPM command, or at least something which acts
-# similarly, and also a dracut command.
+# Virt-v2v needs a /bin/sh, an RPM command and a dracut command, or at
+# least something which acts similarly to those.
+$g->upload ('fedora-static-bin', '/bin/sh');
+$g->chmod (0777, '/bin/sh');
$g->upload ('fedora-static-bin', '/bin/rpm');
$g->chmod (0777, '/bin/rpm');
$g->upload ('fedora-static-bin', '/sbin/dracut');

View File

@ -1,343 +0,0 @@
From 777f3ac82c20469c9e438b9fd88a57007fd2c2bb Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Wed, 19 Feb 2025 14:16:13 +0000
Subject: [PATCH] drivers: Handle large output from 'rpm -ql' command
This requires the new guestfs_sh_out API from libguestfs 1.55.6.
Update common submodule to include:
Richard W.M. Jones (3):
mlstdutils: Reimplement String.find, add String.find_from
mlstdutils: Reimplement String.nsplit tail recursively
mldrivers: Handle large output from 'rpm -ql' command
Fixes: https://issues.redhat.com/browse/RHEL-80214
Reported-by: Nijin Ashok
(cherry picked from commit 5520f1cfae55377c2fe1db3f2974f6006822e0ea)
---
common | 2 +-
m4/guestfs-libraries.m4 | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
Submodule common 766384a45..ee88791e1:
diff --git a/common/mldrivers/linux.ml b/common/mldrivers/linux.ml
index 4e30a8e1f..0dec15495 100644
--- a/common/mldrivers/linux.ml
+++ b/common/mldrivers/linux.ml
@@ -58,76 +58,84 @@ and do_remove g root packages =
let file_list_of_package (g : Guestfs.guestfs) root app =
let package_format = g#inspect_get_package_format root in
- match package_format with
- | "deb" ->
- let cmd = [| "dpkg"; "-L"; app.G.app2_name |] in
- debug "%s" (String.concat " " (Array.to_list cmd));
- let files = g#command_lines cmd in
- let files = Array.to_list files in
+
+ let cmd =
+ match package_format with
+ | "deb" -> sprintf "dpkg -L %s" (quote app.G.app2_name)
+
+ | "rpm" ->
+ (* Since RPM allows multiple packages installed with the same
+ * name, always check the full NEVR here (RHBZ#1161250).
+ *
+ * In RPM < 4.11 query commands that use the epoch number in the
+ * package name did not work.
+ *
+ * For example:
+ * RHEL 6 (rpm 4.8.0):
+ * $ rpm -q tar-2:1.23-11.el6.x86_64
+ * package tar-2:1.23-11.el6.x86_64 is not installed
+ * Fedora 20 (rpm 4.11.2):
+ * $ rpm -q tar-2:1.26-30.fc20.x86_64
+ * tar-1.26-30.fc20.x86_64
+ *)
+ let is_rpm_lt_4_11 () =
+ let ver =
+ try
+ (* Since we're going to run 'rpm' below anyway, seems safe
+ * to run it here and assume the binary works.
+ *)
+ let cmd = [| "rpm"; "--version" |] in
+ debug "%s" (String.concat " " (Array.to_list cmd));
+ let ver = g#command_lines cmd in
+ let ver =
+ if Array.length ver > 0 then ver.(0) else raise Not_found in
+ debug "%s" ver;
+ let ver = String.nsplit " " ver in
+ let ver =
+ match ver with
+ | [ "RPM"; "version"; ver ] -> ver
+ | _ -> raise Not_found in
+ if not (PCRE.matches re_version ver) then raise Not_found;
+ (int_of_string (PCRE.sub 1), int_of_string (PCRE.sub 2))
+ with Not_found ->
+ (* 'rpm' not installed? Hmm... *)
+ (0, 0) in
+ ver < (4, 11)
+ in
+ let pkg_name =
+ if app.G.app2_epoch = Int32.zero || is_rpm_lt_4_11 () then
+ sprintf "%s-%s-%s" app.G.app2_name app.G.app2_version
+ app.G.app2_release
+ else
+ sprintf "%s-%ld:%s-%s" app.G.app2_name app.G.app2_epoch
+ app.G.app2_version app.G.app2_release in
+ sprintf "rpm -ql %s" (quote pkg_name)
+
+ | format ->
+ error (f_"dont know how to get list of files from package using %s")
+ format in
+
+ debug "file_list_of_package: running: %s" cmd;
+
+ (* Some packages have a lot of files, too many to list without
+ * breaking the maximum message size assumption in libguestfs.
+ * To cope with this, use guestfs_sh_out, added in 1.55.6.
+ * https://issues.redhat.com/browse/RHEL-80080
+ *)
+ let tmpfile = Filename.temp_file "v2vcmd" ".out" in
+ On_exit.unlink tmpfile;
+ g#sh_out cmd tmpfile;
+ let files = read_whole_file tmpfile in
+
+ (* RPM prints "(contains no files)" on stdout when a package
+ * has no files in it:
+ * https://github.com/rpm-software-management/rpm/issues/962
+ *)
+ if String.is_prefix files "(contains no files)" then []
+ else (
+ let files = String.nsplit "\n" files in
List.sort compare files
-
- | "rpm" ->
- (* Since RPM allows multiple packages installed with the same
- * name, always check the full NEVR here (RHBZ#1161250).
- *
- * In RPM < 4.11 query commands that use the epoch number in the
- * package name did not work.
- *
- * For example:
- * RHEL 6 (rpm 4.8.0):
- * $ rpm -q tar-2:1.23-11.el6.x86_64
- * package tar-2:1.23-11.el6.x86_64 is not installed
- * Fedora 20 (rpm 4.11.2):
- * $ rpm -q tar-2:1.26-30.fc20.x86_64
- * tar-1.26-30.fc20.x86_64
- *)
- let is_rpm_lt_4_11 () =
- let ver =
- try
- (* Since we're going to run 'rpm' below anyway, seems safe
- * to run it here and assume the binary works.
- *)
- let cmd = [| "rpm"; "--version" |] in
- debug "%s" (String.concat " " (Array.to_list cmd));
- let ver = g#command_lines cmd in
- let ver = if Array.length ver > 0 then ver.(0) else raise Not_found in
- debug "%s" ver;
- let ver = String.nsplit " " ver in
- let ver =
- match ver with
- | [ "RPM"; "version"; ver ] -> ver
- | _ -> raise Not_found in
- if not (PCRE.matches re_version ver) then raise Not_found;
- (int_of_string (PCRE.sub 1), int_of_string (PCRE.sub 2))
- with Not_found ->
- (* 'rpm' not installed? Hmm... *)
- (0, 0) in
- ver < (4, 11)
- in
- let pkg_name =
- if app.G.app2_epoch = Int32.zero || is_rpm_lt_4_11 () then
- sprintf "%s-%s-%s" app.G.app2_name app.G.app2_version
- app.G.app2_release
- else
- sprintf "%s-%ld:%s-%s" app.G.app2_name app.G.app2_epoch
- app.G.app2_version app.G.app2_release in
- let cmd = [| "rpm"; "-ql"; pkg_name |] in
- debug "%s" (String.concat " " (Array.to_list cmd));
- let files = g#command_lines cmd in
- (* RPM prints "(contains no files)" on stdout when a package
- * has no files in it:
- * https://github.com/rpm-software-management/rpm/issues/962
- *)
- if files = [| "(contains no files)" |] then
- []
- else (
- let files = Array.to_list files in
- List.sort compare files
- )
-
- | format ->
- error (f_"dont know how to get list of files from package using %s")
- format
+ )
let is_file_owned (g : G.guestfs) root path =
let package_format = g#inspect_get_package_format root in
diff --git a/common/mlstdutils/std_utils.ml b/common/mlstdutils/std_utils.ml
index 86b21a7c5..1a36ab772 100644
--- a/common/mlstdutils/std_utils.ml
+++ b/common/mlstdutils/std_utils.ml
@@ -98,24 +98,27 @@ module String = struct
and len = length str in
len >= sufflen && sub str (len - sufflen) sufflen = suffix
- let rec find s sub =
- let len = length s in
+ let find_from str pos sub =
let sublen = length sub in
- let rec loop i =
- if i <= len-sublen then (
- let rec loop2 j =
- if j < sublen then (
- if s.[i+j] = sub.[j] then loop2 (j+1)
- else -1
- ) else
- i (* found *)
- in
- let r = loop2 0 in
- if r = -1 then loop (i+1) else r
- ) else
- -1 (* not found *)
- in
- loop 0
+ if sublen = 0 then
+ 0
+ else (
+ let found = ref 0 in
+ let len = length str in
+ try
+ for i = pos to len - sublen do
+ let j = ref 0 in
+ while unsafe_get str (i + !j) = unsafe_get sub !j do
+ incr j;
+ if !j = sublen then begin found := i; raise Exit; end;
+ done;
+ done;
+ -1
+ with
+ Exit -> !found
+ )
+
+ let find str sub = find_from str 0 sub
let rec replace s s1 s2 =
let len = length s in
@@ -145,7 +148,7 @@ module String = struct
else if n >= len then str, ""
else sub str 0 n, sub str n (len-n)
- let rec split sep str =
+ let split sep str =
let seplen = length sep in
let strlen = length str in
let i = find str sep in
@@ -154,20 +157,36 @@ module String = struct
sub str 0 i, sub str (i + seplen) (strlen - i - seplen)
)
- and nsplit ?(max = 0) sep str =
+ let nsplit ?(max = 0) sep str =
if max < 0 then
invalid_arg "String.nsplit: max parameter should not be negative";
- (* If we reached the limit, OR if the pattern does not match the string
- * at all, return the rest of the string as a single element list.
- *)
- if max = 1 || find str sep = -1 then
- [str]
- else (
- let s1, s2 = split sep str in
- let max = if max = 0 then 0 else max - 1 in
- s1 :: nsplit ~max sep s2
- )
+ let len = String.length str in
+ let seplen = String.length sep in
+
+ let rec loop iters posn acc =
+ (* If we reached the limit, OR if the pattern does not match
+ * the string at all, return the rest of the string.
+ *)
+ if max > 0 && iters = max then (
+ let rest =
+ if posn = 0 then str else String.sub str posn (len-posn) in
+ List.rev (rest :: acc)
+ )
+ else (
+ let end_ = find_from str posn sep in
+ if end_ = -1 then (
+ let rest =
+ if posn = 0 then str else String.sub str posn (len-posn) in
+ List.rev (rest :: acc)
+ )
+ else (
+ let acc = String.sub str posn (end_-posn) :: acc in
+ loop (iters+1) (end_+seplen) acc
+ )
+ )
+ in
+ loop 1 0 []
let rec lines_split str =
let buf = Buffer.create 16 in
diff --git a/common/mlstdutils/std_utils.mli b/common/mlstdutils/std_utils.mli
index a39ac5f3b..7bd55fbae 100644
--- a/common/mlstdutils/std_utils.mli
+++ b/common/mlstdutils/std_utils.mli
@@ -82,6 +82,10 @@ module String : sig
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]. *)
diff --git a/common/mlstdutils/std_utils_tests.ml b/common/mlstdutils/std_utils_tests.ml
index 3f5bb1a86..4e368152f 100644
--- a/common/mlstdutils/std_utils_tests.ml
+++ b/common/mlstdutils/std_utils_tests.ml
@@ -113,13 +113,19 @@ let test_string_nsplit ctx =
assert_equal_stringlist [""] (String.nsplit " " "");
assert_equal_stringlist ["abc"] (String.nsplit " " "abc");
assert_equal_stringlist ["a"; "b"; "c"] (String.nsplit " " "a b c");
+ assert_equal_stringlist ["abc"; "d"; "e"] (String.nsplit " " "abc d e");
assert_equal_stringlist ["a"; "b"; "c"; ""] (String.nsplit " " "a b c ");
assert_equal_stringlist [""; "a"; "b"; "c"] (String.nsplit " " " a b c");
assert_equal_stringlist [""; "a"; "b"; "c"; ""] (String.nsplit " " " a b c ");
assert_equal_stringlist ["a b c d"] (String.nsplit ~max:1 " " "a b c d");
assert_equal_stringlist ["a"; "b c d"] (String.nsplit ~max:2 " " "a b c d");
assert_equal_stringlist ["a"; "b"; "c d"] (String.nsplit ~max:3 " " "a b c d");
- assert_equal_stringlist ["a"; "b"; "c"; "d"] (String.nsplit ~max:10 " " "a b c d")
+ assert_equal_stringlist ["a"; "b"; "c"; "d"] (String.nsplit ~max:10 " " "a b c d");
+
+ (* Test that nsplit can handle large strings. *)
+ let xs = Array.to_list (Array.make 10_000_000 "xyz") in
+ let xs_concat = String.concat " " xs in
+ assert_equal_stringlist xs (String.nsplit " " xs_concat)
(* Test Std_utils.String.lines_split. *)
let test_string_lines_split ctx =
diff --git a/m4/guestfs-libraries.m4 b/m4/guestfs-libraries.m4
index 80f9425f0..7c66853dd 100644
--- a/m4/guestfs-libraries.m4
+++ b/m4/guestfs-libraries.m4
@@ -19,9 +19,8 @@ dnl Any C libraries required by the libguestfs C library (not the daemon).
dnl Of course we need libguestfs.
dnl
-dnl We need libguestfs 1.49.8 for guestfs_inspect_get_build_id in
-dnl virt-drivers.
-PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.49.8])
+dnl We need libguestfs >= 1:1.54.0-4.el9_6 for guestfs_sh_out.
+PKG_CHECK_MODULES([LIBGUESTFS], [libguestfs >= 1.54.0])
dnl Test if it's GNU or XSI strerror_r.
AC_FUNC_STRERROR_R

View File

@ -1,33 +0,0 @@
From 28d6901c72cb956f1fb13c9b6dd50691f1ccfb49 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Tue, 11 Mar 2025 11:41:34 +0000
Subject: [PATCH] Update common submodule
Richard W.M. Jones (1):
mlcustomize: Remove dnf --verbose option
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2351282
Cherry picked from commit bb3d0e5bc5f08300ce36bcccf91d02d9d7f32343
and modified to only include dnf --verbose fix.
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common ee88791e1..31d279a79:
diff --git a/common/mlcustomize/guest_packages.ml b/common/mlcustomize/guest_packages.ml
index 2602fc718..96614b6cc 100644
--- a/common/mlcustomize/guest_packages.ml
+++ b/common/mlcustomize/guest_packages.ml
@@ -61,10 +61,7 @@ let install_command packages package_management =
apt-get $apt_opts update
apt-get $apt_opts install %s
" quoted_args
- | "dnf" ->
- sprintf "dnf%s -y install %s"
- (if verbose () then " --verbose" else "")
- quoted_args
+ | "dnf" -> sprintf "dnf -y install %s" quoted_args
| "pisi" -> sprintf "pisi it %s" quoted_args
| "pacman" -> sprintf "pacman -S --noconfirm %s" quoted_args
| "urpmi" -> sprintf "urpmi %s" quoted_args

View File

@ -1,51 +0,0 @@
From 6fc2e63a599311eeff6f02588b9a8f7851141483 Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones@redhat.com>
Date: Fri, 15 Aug 2025 16:58:08 +0100
Subject: [PATCH] Update common submodule
Pick up the commit below, to ensure that the firstboot.bat file we
inject into Windows is the same as the one from virt-v2v.
commit b40e534fefb74af32bd496904e44ce9bca1a7b34
Author: Vadim Rozenfeld <vrozenfe@redhat.com>
Date: Thu Jul 10 10:48:04 2025 +1000
Modify the firstboot script to check the scripts
execution return status
Related: https://issues.redhat.com/browse/RHEL-100682
Signed-off-by: Vadim Rozenfeld <vrozenfe@redhat.com>
Fixes: https://issues.redhat.com/browse/RHEL-109521
---
common | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Submodule common 31d279a79..6a822ba7b:
diff --git a/common/mlcustomize/firstboot.ml b/common/mlcustomize/firstboot.ml
index 52e76401e..aa3ea98ad 100644
--- a/common/mlcustomize/firstboot.ml
+++ b/common/mlcustomize/firstboot.ml
@@ -305,13 +305,19 @@ if not exist \"%%scripts_done%%\" (
:: Pick the next script to run.
for %%%%f in (\"%%scripts%%\"\\*.bat) do (
echo running \"%%%%f\"
- move \"%%%%f\" \"%%scripts_done%%\"
- pushd \"%%scripts_done%%\"
+ pushd \"%%scripts%%\"
call \"%%%%~nf\"
set elvl=!errorlevel!
echo .... exit code !elvl!
popd
+ if !elvl! NEQ 249 (
+ echo Script succeeded, moving to scripts-done
+ move \"%%%%f\" \"%%scripts_done%%\"
+ ) else (
+ echo Script failed, will retry on next boot
+ )
+
:: Reboot the computer. This is necessary to free any locked
:: files which may prevent later scripts from running.
shutdown /r /t 0 /y

View File

@ -1,17 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCAAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmb+mWcRHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKBPWRAAmHJHvz8GRAsFEpZS6/6FjgxjASRTtMZO
02vo8KZLpF3pX0zjsgcYPsTgj90kQ8z9rsdXk70HbOvnJIuVShuT9Q/bGiYf60YB
CEvRy3b5HMgsk4Dk46Ux0RpOHTFmVKOxSdNrk1G0qRMjIYdy19KxRnMJyQXv4QRg
y6RYOt2Zm6Luj53Id+zTLiqnz5Z8PBkupWH3y1zSrN3OcASIvSKYnPUA/c63+Fzk
YZHGIf3DCHEAnzHfPMaF58L+Np3ZaC4vGBfnDfLiyTd/d2J/Ci18LcI9hC9l6SV1
ePlNBH/LV1+YYuWLhd9XPVsCiKi2zY3/DMxoxZcYhl+JalVTeK6FZk2Abe+0c9XZ
wAaQG+aLqweDHNiLJ0AxoPqinWsa2EpciZMKAzzCGM83IABm+pKSZlN077riiYNa
YRZIw/i6LFfuQSxBaav+/d6cOpxx4AklmaV1ymu4Xr2JTm4u93O72722oyhCzbAn
3DQac1H5XgJsBh6Un9Ybl3PkUGS2AlCCDTFbyWDB8i9aiWv5m/yuLD4c6hk9sRWQ
DNiH0AKaem/cPt33FV3C2viyppmGnhZDNrrKKzJCxCkRY7XU2rzEJ1SmU9CACCOj
ick58Flv52CYSeonC+7uO9jqlDcgVmJIDitCCHhIl1Kipr1mzCMQV1Vq0LP3Hv8f
MSbFdmbrh5I=
=Gu1k
-----END PGP SIGNATURE-----

View File

@ -7,7 +7,7 @@ set -e
# ./copy-patches.sh
project=guestfs-tools
rhel_version=9.7
rhel_version=10.2
# Check we're in the right directory.
if [ ! -f $project.spec ]; then

View File

@ -0,0 +1,17 @@
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEE93dPsa0HSn6Mh2fqkXOPc+G3aKAFAmgs7icRHHJpY2hAYW5u
ZXhpYS5vcmcACgkQkXOPc+G3aKAPvg/+K1KSQ7VrdxRkaUhXTVeiuSGGpdF8T+Rs
eROR6WivkbOet0E++EcOHL5fXneQUkXEI0t2tWSG9KRw236xDDsHsQAeA4eLjDJ3
Tl0QaPho8uH4zOOHpw1IWflycJjrvMhdgPxeiI++PfeADPyDfzXTlPMQpJ+WjnJn
y+vousuCZfn4c1SStphMNXCDMoh4XEOKktpICg3DeswwdVb8FVFi4gNr+iI/0QuY
jQUbpZCZnxtgAvAHe7epttxRKQDz2HosHIED0rRYqh9cNtlk34awm6LtQnhPk3Hp
QF3nUy126uISohyd48TWiqCXnzK3+eJmnvxSv0xvTFKm/bXKTidXH25Na/R9o0Df
eE0M1boCuwTaXeO5kOuheJmFcd5NTJHHDF1uSpLtKxABszePYewLwyCTQg/qT2r6
pab4VaLeSdJDJzvDXUwgZlfZflMg49eKMpa87ub0i7MuHkQgddURlkYchfmq/dvR
K1AHYZxRQn8VjYEVEBKIUJDC7q4b54CnOfpwngnGRPTycj/sYOOteFPi3dDL4Wnk
hfosTlGAPlF6g3mT4Jjpev1OzKO6gUBpBIv0e/V2Fow5n9oBRV7fYpWO96KSZXkb
sK2abDZPkvXcZf6gWrWb9ZkELBFgX7vI7DiG19/vO/J70kbjolbzgHUVEvp6i5RU
Q2j56e6XWG0=
=GfAw
-----END PGP SIGNATURE-----

View File

@ -7,19 +7,16 @@
# Verify tarball signature with GPGv2.
%global verify_tarball_signature 1
# If there are patches which touch autotools files, set this to 1.
%global patches_touch_autotools 1
# The source directory.
%global source_directory 1.52-stable
%global source_directory 1.54-stable
# Filter perl provides.
%{?perl_default_filter}
Summary: Tools to access and modify virtual machine disk images
Name: guestfs-tools
Version: 1.52.2
Release: 6%{?dist}
Version: 1.54.0
Release: 10%{?dist}
License: GPL-2.0-or-later AND LGPL-2.0-or-later
# Build only for architectures that have a kernel
@ -45,29 +42,55 @@ Source2: libguestfs.keyring
Source3: copy-patches.sh
# Patches are maintained in the following repository:
# https://github.com/rwmjones/guestfs-tools/commits/rhel-9.7
# https://github.com/rwmjones/guestfs-tools/commits/rhel-10.2
# Patches.
Patch0001: 0001-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
Patch0002: 0002-RHEL-builder-Disable-opensuse-repository.patch
Patch0003: 0003-customize-Implement-inject-blnsvr-operation.patch
Patch0004: 0004-build-Add-new-dependency-on-json-c.patch
Patch0005: 0005-builder-Replace-jansson-with-json-c.patch
Patch0006: 0006-build-Remove-Jansson-dependency.patch
Patch0007: 0007-test-data-phony-fedora-Add-simple-static-bin-sh.patch
Patch0008: 0008-drivers-Handle-large-output-from-rpm-ql-command.patch
Patch0009: 0009-Update-common-submodule.patch
Patch0010: 0010-builder-Update-link-to-templates-to-use-https.patch
Patch0011: 0011-Update-common-submodule.patch
%if 0%{patches_touch_autotools}
BuildRequires: autoconf, automake, libtool, gettext-devel
%endif
Patch0001: 0001-docs-Move-release-note-about-GNU-gettext-to-build-se.patch
Patch0002: 0002-builder-Update-link-to-templates-to-use-https.patch
Patch0003: 0003-builder-Replace-cpu-host-with-cpu-max-in-example.patch
Patch0004: 0004-customize-Fixes-for-selinux-relabelling-and-Windows-.patch
Patch0005: 0005-Update-common-submodule.patch
Patch0006: 0006-.gitignore-Ignore-.bak-files.patch
Patch0007: 0007-builder-sysprep-Use-quoted-string-literals-in-a-few-.patch
Patch0008: 0008-builder-templates-make-template.ml-Fix-quoting.patch
Patch0009: 0009-builder-templates-make-template.ml-Use-quoted-string.patch
Patch0010: 0010-builder-templates-make-template.ml-Add-str-and-unix-.patch
Patch0011: 0011-daemon-generator-Use-power-of-2-for-initial-size-of-.patch
Patch0012: 0012-builder-Build-fedora-42-template.patch
Patch0013: 0013-Update-common-submodule.patch
Patch0014: 0014-common-update-submodule.patch
Patch0015: 0015-pod-Document-removal-of-sm-options.patch
Patch0016: 0016-test-data-phony-guests-Increase-size-of-Windows-imag.patch
Patch0017: 0017-inspector-Add-new-class-field-to-output-of-virt-insp.patch
Patch0018: 0018-inspector-Add-windows_group_policy-is-Windows-GPOs-d.patch
Patch0019: 0019-inspector-For-xfs-try-to-find-and-print-the-filesyst.patch
Patch0020: 0020-Sort-some-entries-in-.gitignore-into-order.patch
Patch0021: 0021-build-Add-NULL-as-a-convenient-list-terminator.patch
Patch0022: 0022-Move-virt-filesystems-virt-log-virt-ls-virt-tail-to-.patch
Patch0023: 0023-filesystems-Optionally-display-filesystem-version.patch
Patch0024: 0024-Update-common-submodule.patch
Patch0025: 0025-Update-common-submodule.patch
Patch0026: 0026-Update-common-submodule.patch
Patch0027: 0027-common-update-submodule.patch
Patch0028: 0028-common-update-submodule.patch
Patch0029: 0029-virt-builder-document-Windows-firstboot-exit-code-be.patch
Patch0030: 0030-virt-builder-document-exit-code-250-for-Windows-firs.patch
Patch0031: 0031-common-update-submodule.patch
Patch0032: 0032-sysprep-Remove-documentation-about-copying-and-cloni.patch
Patch0033: 0033-sysprep-Improve-synopsis-section.patch
Patch0034: 0034-sysprep-Rework-documentation.patch
Patch0035: 0035-customize-sysprep-Move-firstboot-docs-from-sysprep-c.patch
Patch0036: 0036-builder-customize-Combine-and-rework-firstboot-docum.patch
Patch0037: 0037-customize-Document-location-of-Windows-sentinel-file.patch
Patch0038: 0038-RHEL-Reject-use-of-libguestfs-winsupport-features-ex.patch
Patch0039: 0039-RHEL-builder-Disable-opensuse-repository.patch
# Basic build requirements.
BuildRequires: autoconf, automake, libtool, gettext-devel
BuildRequires: gcc, gcc-c++
BuildRequires: make
BuildRequires: libguestfs-devel >= 1:1.54.0-4.el9
BuildRequires: glibc-utils
BuildRequires: libguestfs-devel >= 1:1.58.1-6
BuildRequires: libguestfs-xfs
BuildRequires: perl(Pod::Simple)
BuildRequires: perl(Pod::Man)
@ -85,12 +108,10 @@ BuildRequires: ncurses-devel
%ifarch x86_64
BuildRequires: glibc-static
%endif
BuildRequires: ocaml >= 4.08
BuildRequires: ocaml-libguestfs-devel
BuildRequires: ocaml-findlib-devel
BuildRequires: ocaml-gettext-devel
%if !0%{?rhel}
BuildRequires: ocaml-ounit-devel
%endif
BuildRequires: flex
BuildRequires: bison
BuildRequires: xz-devel
@ -115,9 +136,8 @@ BuildRequires: perl-generators
BuildRequires: gnupg2
%endif
# Ensure a minimum version of libguestfs is installed. This contains
# new APIs sh-out and command-out, required by virt-drivers.
Requires: libguestfs >= 1:1.54.0-4.el9
# Ensure a minimum version of libguestfs is installed.
Requires: libguestfs%{?_isa} >= 1:1.58.1-6
# For virt-builder:
Requires: curl
@ -262,13 +282,12 @@ for %{name}.
%setup -q
%autopatch -p1
%if 0%{patches_touch_autotools}
autoreconf -i
%endif
%build
%{configure}
autoreconf -fiv
# Preserve timestamps when copying files. Otherwise, the time of the
# build ends up in the header added by gzip when it compresses files.
%{configure} INSTALL='/usr/bin/install -p'
# Building index-parse.c by hand works around a race condition in the
# autotools cruft, where two or more copies of yacc race with each
@ -416,102 +435,200 @@ end
%changelog
* Fri Aug 15 2025 Richard W.M. Jones <rjones@redhat.com> - 1.52.2-6
- Update guestfs-tools firstboot.bat to match virt-v2v
resolves: RHEL-109521
* Thu May 07 2026 Richard W.M. Jones <rjones@redhat.com> - 1.54.0-10
- Fix binary LUKS keys
resolves: RHEL-174518
- Windows firstboot: Add exit code 250 to skip reboots
Rework documentation for firstboot feature
resolves: RHEL-174517
- Write sentinel file after firstboot scripts finish
related: RHEL-161192
- Fix location of Windows Vista and Windows 2008 Server R1 drivers
related: RHEL-174513
* Tue Jun 10 2025 Richard W.M. Jones <rjones@redhat.com> - 1.52.2-5
* Thu Feb 05 2026 Richard W.M. Jones <rjones@redhat.com> - 1.54.0-9
- Synchronize spec file with Fedora
- Fix pnputils after virt-customize --inject-virtio-win
resolves: RHEL-116537
- Unify spec files between Fedora and RHEL.
- Ensure a minimum version of libguestfs is installed at build and run time.
resolves: RHEL-116716
- Remove virt-customize subscription-manager options
resolves: RHEL-122307
- Add AV and GPOs to virt-inspector output
resolves: RHEL-125955
- Expose XFS version in virt-filesystems
resolves: RHEL-144074
* Wed Aug 13 2025 Richard W.M. Jones <rjones@redhat.com> - 1.54.0-3
- Rebase to guestfs-tools 1.54.0
resolves: RHEL-81734
- virt-builder, virt-v2v & other tools with -v and --install causes dnf5 error
resolves: RHEL-83201
- virt-drivers fails on opensuse guest if kernel-source is installed
resolves: RHEL-92604
- builder: Update link to templates to use https
resolves: RHEL-94874
* Thu Mar 13 2025 Richard W.M. Jones <rjones@redhat.com> - 1.52.2-4
- mlcustomize: Remove dnf --verbose option
resolves: RHEL-83200
* Tue Feb 25 2025 Richard W.M. Jones <rjones@redhat.com> - 1.52.2-3
- Fix virt-drivers fails on opensuse guest if kernel-source is installed
resolves: RHEL-80214
resolves: RHEL-94873
- Fix SELinux relabelling in Linux split-/usr
resolves: RHEL-109129
* Wed Oct 30 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.2-2
- Rebase to guestfs-tools 1.52.2
resolves: RHEL-56811
resolves: RHEL-56812
- Replace Jansson with json-c
resolves: RHEL-65294
resolves: RHEL-65295
* Tue Aug 27 2024 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-5
* Tue Aug 27 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.1-1
- New stable version 1.52.1
- Rebase on top of patches from RHEL 9.5
- Reboot Windows between each firstboot script to improve reliability
resolves: RHEL-55759
* Thu May 16 2024 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-4
- Add support for nbd+unix:// URIs
resolves: RHEL-33956
resolves: RHEL-56319
- customize: Implement --inject-blnsvr operation
resolves: RHEL-36634
resolves: RHEL-56330
- Add support for nbd+unix:// URIs
resolves: RHEL-56332
* Fri Jan 19 2024 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-2
- Rebase to guestfs-tools 1.51.6
- Implement --key all:...
resolves: RHEL-19030
- Fix crash because of off-by-one error
resolves: RHEL-19062
- Fix virt-customize --chown invalid format
resolves: RHEL-21899
* Tue Jun 25 2024 Troy Dawson <tdawson@redhat.com> - 1.52.0-6
- Bump release for June 2024 mass rebuild
* Thu Jun 08 2023 Laszlo Ersek <lersek@redhat.com> - 1.50.1-3
- let virt-inspector recognize "--key /dev/mapper/VG-LV:key:password"
- reenable "make check"; we now use "-cpu max" (libguestfs 30f74f38bd6e)
resolves: rhbz#2209280
* Wed Jun 19 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.0-5
- OCaml 5.2.0 ppc64le fix
* Thu Apr 06 2023 Richard W.M. Jones <rjones@redhat.com> - 1.50.1-1
- Rebase to guestfs-tools 1.50.1
resolves: rhbz#2168626
- Fix virt-drivers inspection of RHEL 9.2 guests
resolves: rhbz#2184963
* Fri May 31 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.0-4
- Rebuild for OCaml 5.2
* Thu Nov 24 2022 Richard W.M. Jones <rjones@redhat.com> - 1.48.2-8
- Support Rocky Linux in virt-customize
resolves: rhbz#2133443
- Disable OpenSUSE repo in virt-builder
resolves: rhbz#2145160
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.52.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Fri Jul 15 2022 Richard W.M. Jones <rjones@redhat.com> - 1.48.2-5
- Rebase to guestfs-tools 1.48.2
resolves: rhbz#2059286
- Default to --selinux-relabel in various tools
resolves: rhbz#2075718, rhbz#2089748
- Add lvm system.devices cleanup operation to virt-sysprep
resolves: rhbz#2072493
- Refactor virt-customize --install, --update options in common submodule
- Add support for Clevis & Tang
resolves: rhbz#1809453
- Fix CVE-2022-2211 Denial of Service in --key parameter
resolves: rhbz#2102721
- Fix virt-sysprep and LUKS-on-LVM guests
resolves: rhbz#2106286
* Fri Jan 19 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.0-2
- Fix virt-customize --chown invalid format error
- New upstream github repository.
* Sat Dec 04 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-6
- Clean up NetworkManager connection files
- Add the copy-patches.sh script from virt-v2v
resolves: rhbz#1980922
* Thu Jan 4 2024 Richard W.M. Jones <rjones@redhat.com> - 1.52.0-1
- New stable version 1.52.0
* Tue Nov 23 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-5
- Fix detection of Kylin Desktop
resolves: rhbz#2025950
* Tue Dec 19 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.7-1
- New development version 1.51.7
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 1.46.1-4.1
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Mon Dec 18 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-5
- OCaml 5.1.1 + s390x code gen fix for Fedora 40
* Wed Jun 2 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-3.el9.1
* Tue Dec 12 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-4
- Bump release and rebuild
* Tue Dec 12 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-3
- OCaml 5.1.1 rebuild for Fedora 40
* Sat Dec 9 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.6-2
- New development version 1.51.6
* Mon Nov 27 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.5-2
- Fix build for libxml2 2.12.1
* Thu Nov 02 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.5-1
- New development version 1.51.5
* Thu Oct 05 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.4-2
- OCaml 5.1 rebuild for Fedora 40
* Thu Jul 20 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.4-1
- New development version 1.51.4
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.51.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Fri Jul 14 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.3-1
- New development version 1.51.3
* Mon Jun 05 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.2-2
- Migrated to SPDX license
* Thu Apr 06 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.2-1
- New development version 1.51.2
* Tue Feb 21 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.1-2
- Fix BR hwdata-devel for PCI IDs data
* Mon Feb 20 2023 Richard W.M. Jones <rjones@redhat.com> - 1.51.1-1
- New development version 1.51.1
- virt-drivers: Add BuildRequires and runtime Recommends on hwdata.
* Tue Feb 14 2023 Richard W.M. Jones <rjones@redhat.com> - 1.50.0-2
- Remove virt-dib (RHBZ#2169550)
* Tue Feb 07 2023 Richard W.M. Jones <rjones@redhat.com> - 1.50.0-1
- New upstream stable version 1.50.0
* Thu Jan 26 2023 Richard W.M. Jones <rjones@redhat.com> - 1.49.10-1
- New upstream development version 1.49.10
* Thu Jan 19 2023 Richard W.M. Jones <rjones@redhat.com> - 1.49.9-1
- New upstream development version 1.49.9
- New tool: virt-drivers
- Add BR glibc-static for tests on x86_64.
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.49.8-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Jan 17 2023 Richard W.M. Jones <rjones@redhat.com> - 1.49.8-2
- New upstream development version 1.49.8
- +BR libosinfo-devel
* Sat Dec 10 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.7-2
- New upstream development version 1.49.7
* Fri Nov 25 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.6-1
- New upstream development version 1.49.6
- Enable opensuse repository again
* Mon Nov 21 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.5-2
- Disable opensuse repository
* Wed Oct 12 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.5-1
- New upstream development version 1.49.5
* Mon Aug 01 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.4-1
- New upstream development version 1.49.4
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.49.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Fri Jul 01 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.3-1
- New upstream development version 1.49.3
* Thu May 26 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.2-1
- New upstream development version 1.49.2
* Thu May 12 2022 Richard W.M. Jones <rjones@redhat.com> - 1.49.1-1
- New upstream development version 1.49.1
* Mon Mar 14 2022 Richard W.M. Jones <rjones@redhat.com> - 1.48.0-1
- New upstream stable branch version 1.48.0
* Tue Mar 08 2022 Richard W.M. Jones <rjones@redhat.com> - 1.47.5-1
- New upstream development version 1.47.8
- Add new guestfs-tools-release-notes-1.48(1) man page.
* Tue Mar 01 2022 Richard W.M. Jones <rjones@redhat.com> - 1.47.4-1
- New upstream development version 1.47.4
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.47.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Sat Dec 04 2021 Richard W.M. Jones <rjones@redhat.com> - 1.47.3-1
- New upstream development version 1.47.3
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.47.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Wed Jun 16 2021 Richard W.M. Jones <rjones@redhat.com> - 1.47.2-1
- New upstream development version 1.47.2
* Wed Jun 2 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-3
- Add gating tests (for RHEL 9)
* Mon May 17 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-3
- Fix virt-win-reg --version
resolves: rhbz#1961160
* Thu May 13 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-2
- BR perl-generators so deps of virt-win-reg subpackage are correct.
resolves: rhbz#1960191
* Sat May 08 2021 Richard W.M. Jones <rjones@redhat.com> - 1.46.1-1
- New stable branch version 1.46.1.

2
sources Normal file
View File

@ -0,0 +1,2 @@
SHA512 (guestfs-tools-1.54.0.tar.gz) = db76a1cbfaa8b53b5c4609030f545b9d043161cebf54379da6418800086855f11cb3a0e5d135184c2a885094a6a7120155774377a6641a2d7fbd45206ff9ec87
SHA512 (libguestfs.keyring) = 297a15edc7c220222b9f650e0a9361ae132d3f0fed04aeb2237a1d9c3f6dac6f336846434f66480faed72635a33f659e849b052e74b88d1508aeff03f8c9a2ac