823793
From 7dbcddd5bd5939493db74843593316f7101f8fde Mon Sep 17 00:00:00 2001
823793
From: "Richard W.M. Jones" <rjones@redhat.com>
823793
Date: Thu, 1 Dec 2022 10:00:46 +0000
823793
Subject: [PATCH] New API: inspect_get_build_id
823793
823793
Add an API to return the build ID of the guest.  This to allow a
823793
future change to be able to distinguish between Windows 10 and Windows 11
823793
which can only be done using the build ID.
823793
823793
For Windows we can read the CurrentBuildNumber key from the registry.
823793
For Linux there happens to be a BUILD_ID field in /etc/os-release.
823793
I've never seen a Linux distro that actually uses this.
823793
823793
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
823793
(cherry picked from commit f3dd67affe3c657af64ee9f6d70a16e965309556)
823793
---
823793
 daemon/inspect.ml               |  6 ++++++
823793
 daemon/inspect_fs_unix.ml       |  2 ++
823793
 daemon/inspect_fs_windows.ml    | 14 ++++++++++++++
823793
 daemon/inspect_types.ml         |  5 +++++
823793
 daemon/inspect_types.mli        |  1 +
823793
 generator/actions_inspection.ml | 19 +++++++++++++++++++
823793
 generator/proc_nr.ml            |  3 ++-
823793
 lib/MAX_PROC_NR                 |  2 +-
823793
 8 files changed, 50 insertions(+), 2 deletions(-)
823793
823793
diff --git a/daemon/inspect.ml b/daemon/inspect.ml
823793
index fb75b4a6c..20217c025 100644
823793
--- a/daemon/inspect.ml
823793
+++ b/daemon/inspect.ml
823793
@@ -335,6 +335,12 @@ and inspect_get_hostname root =
823793
   | Some v -> v
823793
   | None -> "unknown"
823793
 
823793
+and inspect_get_build_id root =
823793
+  let root = search_for_root root in
823793
+  match root.inspection_data.build_id with
823793
+  | Some v -> v
823793
+  | None -> "unknown"
823793
+
823793
 and inspect_get_windows_systemroot root =
823793
   let root = search_for_root root in
823793
   match root.inspection_data.windows_systemroot with
823793
diff --git a/daemon/inspect_fs_unix.ml b/daemon/inspect_fs_unix.ml
823793
index 63cb279d0..009195f80 100644
823793
--- a/daemon/inspect_fs_unix.ml
823793
+++ b/daemon/inspect_fs_unix.ml
823793
@@ -96,6 +96,8 @@ let rec parse_os_release release_file data =
823793
            data.product_name <- Some value
823793
          else if key = "VERSION_ID" then
823793
            parse_os_release_version_id value data
823793
+         else if key = "BUILD_ID" then
823793
+           data.build_id <- Some value
823793
        ) values;
823793
 
823793
      (* If we haven't got all the fields, exit right away. *)
823793
diff --git a/daemon/inspect_fs_windows.ml b/daemon/inspect_fs_windows.ml
823793
index c4a05bc38..7bc5de7f7 100644
823793
--- a/daemon/inspect_fs_windows.ml
823793
+++ b/daemon/inspect_fs_windows.ml
823793
@@ -263,6 +263,20 @@ and check_windows_software_registry software_hive data =
823793
          with
823793
            Not_found -> ()
823793
         );
823793
+
823793
+        (* CurrentBuildNumber (build_id).
823793
+         *
823793
+         * In modern Windows, the "CurrentBuild" and "CurrentBuildNumber"
823793
+         * keys are the same.  But in Windows XP, "CurrentBuild"
823793
+         * contained something quite different.  So always use
823793
+         * "CurrentBuildNumber".
823793
+         *)
823793
+        (try
823793
+           let v = List.assoc "CurrentBuildNumber" values in
823793
+           data.build_id <- Some (Hivex.value_string h v)
823793
+         with
823793
+           Not_found -> ()
823793
+        );
823793
       with
823793
       | Not_found ->
823793
          if verbose () then
823793
diff --git a/daemon/inspect_types.ml b/daemon/inspect_types.ml
823793
index 9395c51f9..328a2146b 100644
823793
--- a/daemon/inspect_types.ml
823793
+++ b/daemon/inspect_types.ml
823793
@@ -48,6 +48,7 @@ and inspection_data = {
823793
   mutable version : version option;
823793
   mutable arch : string option;
823793
   mutable hostname : string option;
823793
+  mutable build_id : string option;
823793
   mutable fstab : fstab_entry list;
823793
   mutable windows_systemroot : string option;
823793
   mutable windows_software_hive : string option;
823793
@@ -167,6 +168,8 @@ and string_of_inspection_data data =
823793
              data.arch;
823793
   Option.may (fun v -> bpf "    hostname: %s\n" v)
823793
              data.hostname;
823793
+  Option.may (fun v -> bpf "    build ID: %s\n" v)
823793
+             data.build_id;
823793
   if data.fstab <> [] then (
823793
     let v = List.map (
823793
       fun (a, b) -> sprintf "(%s, %s)" (Mountable.to_string a) b
823793
@@ -272,6 +275,7 @@ let null_inspection_data = {
823793
   version = None;
823793
   arch = None;
823793
   hostname = None;
823793
+  build_id = None;
823793
   fstab = [];
823793
   windows_systemroot = None;
823793
   windows_software_hive = None;
823793
@@ -294,6 +298,7 @@ let merge_inspection_data child parent =
823793
   parent.version <-         merge child.version parent.version;
823793
   parent.arch <-            merge child.arch parent.arch;
823793
   parent.hostname <-        merge child.hostname parent.hostname;
823793
+  parent.build_id <-        merge child.build_id parent.build_id;
823793
   parent.fstab <-           child.fstab @ parent.fstab;
823793
   parent.windows_systemroot <-
823793
     merge child.windows_systemroot parent.windows_systemroot;
823793
diff --git a/daemon/inspect_types.mli b/daemon/inspect_types.mli
823793
index 29c76e8ab..05a3ffd4e 100644
823793
--- a/daemon/inspect_types.mli
823793
+++ b/daemon/inspect_types.mli
823793
@@ -51,6 +51,7 @@ and inspection_data = {
823793
   mutable version : version option;
823793
   mutable arch : string option;
823793
   mutable hostname : string option;
823793
+  mutable build_id : string option;
823793
   mutable fstab : fstab_entry list;
823793
   mutable windows_systemroot : string option;
823793
   mutable windows_software_hive : string option;
823793
diff --git a/generator/actions_inspection.ml b/generator/actions_inspection.ml
823793
index f8b744993..70de22ec0 100644
823793
--- a/generator/actions_inspection.ml
823793
+++ b/generator/actions_inspection.ml
823793
@@ -529,6 +529,25 @@ hive is a valid Windows Registry hive.
823793
 
823793
 You can use C<guestfs_hivex_open> to read or write to the hive.
823793
 
823793
+Please read L<guestfs(3)/INSPECTION> for more details." };
823793
+
823793
+  { defaults with
823793
+    name = "inspect_get_build_id"; added = (1, 49, 8);
823793
+    style = RString (RPlainString, "buildid"), [String (Mountable, "root")], [];
823793
+    impl = OCaml "Inspect.inspect_get_build_id";
823793
+    shortdesc = "get the system build ID";
823793
+    longdesc = "\
823793
+This returns the build ID of the system, or the string
823793
+C<\"unknown\"> if the system does not have a build ID.
823793
+
823793
+For Windows, this gets the build number.  Although it is
823793
+returned as a string, it is (so far) always a number.  See
823793
+L<https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions>
823793
+for some possible values.
823793
+
823793
+For Linux, this returns the C<BUILD_ID> string from
823793
+F</etc/os-release>, although this is not often used.
823793
+
823793
 Please read L<guestfs(3)/INSPECTION> for more details." };
823793
 
823793
   { defaults with
823793
diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml
823793
index edd9bd99d..0f17b1c06 100644
823793
--- a/generator/proc_nr.ml
823793
+++ b/generator/proc_nr.ml
823793
@@ -514,7 +514,8 @@ let proc_nr = [
823793
 509, "cryptsetup_close";
823793
 510, "internal_list_rpm_applications";
823793
 511, "internal_readdir";
823793
-512, "clevis_luks_unlock"
823793
+512, "clevis_luks_unlock";
823793
+513, "inspect_get_build_id";
823793
 ]
823793
 
823793
 (* End of list.  If adding a new entry, add it at the end of the list
823793
diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR
823793
index 4d0e90cbc..31cf34b8d 100644
823793
--- a/lib/MAX_PROC_NR
823793
+++ b/lib/MAX_PROC_NR
823793
@@ -1 +1 @@
823793
-512
823793
+513
823793
-- 
823793
2.31.1
823793