Blame SOURCES/0067-v2v-Fix-RPM-file-owned-test-RHBZ-1503958.patch

a30de4
From 35372c4b210bc49969bf96e7a17897ec29ba4625 Mon Sep 17 00:00:00 2001
a30de4
From: "Richard W.M. Jones" <rjones@redhat.com>
a30de4
Date: Thu, 19 Oct 2017 12:05:43 +0100
a30de4
Subject: [PATCH] v2v: Fix RPM file owned test (RHBZ#1503958).
a30de4
a30de4
Linux.file_owner is not used by any other function, so remove it.
a30de4
a30de4
Linux.is_file_owned is only used when removing kmod-xenpv on old RHEL
a30de4
releases, and so is only required to work for RPM.
a30de4
a30de4
The old file_owner/is_file_owned functions were completely broken for
a30de4
the RPM case.  This replaces them with a simpler, working
a30de4
implementation of is_file_owned only.
a30de4
a30de4
Thanks: Ming Xie for finding and reporting the original bug.
a30de4
(cherry picked from commit e6bc59a7d46707f5037afc8a73206d2773c3fccd)
a30de4
---
a30de4
 v2v/linux.ml  | 61 ++++++++++++++++++++++++++---------------------------------
a30de4
 v2v/linux.mli |  3 ---
a30de4
 2 files changed, 27 insertions(+), 37 deletions(-)
a30de4
a30de4
diff --git a/v2v/linux.ml b/v2v/linux.ml
a30de4
index fad9b0c61..11b0e2cbf 100644
a30de4
--- a/v2v/linux.ml
a30de4
+++ b/v2v/linux.ml
a30de4
@@ -98,7 +98,7 @@ let file_list_of_package (g : Guestfs.guestfs) inspect app =
a30de4
     error (f_"don't know how to get list of files from package using %s")
a30de4
       format
a30de4
 
a30de4
-let rec file_owner (g : G.guestfs) { i_package_format = package_format } path =
a30de4
+let is_file_owned (g : G.guestfs) { i_package_format = package_format } path =
a30de4
   match package_format with
a30de4
   | "deb" ->
a30de4
       (* With dpkg usually the directories are owned by all the packages
a30de4
@@ -108,48 +108,41 @@ let rec file_owner (g : G.guestfs) { i_package_format = package_format } path =
a30de4
        *)
a30de4
       let cmd = [| "dpkg"; "-S"; path |] in
a30de4
       debug "%s" (String.concat " " (Array.to_list cmd));
a30de4
-      let lines =
a30de4
-        try g#command_lines cmd
a30de4
-        with Guestfs.Error msg as exn ->
a30de4
-          if String.find msg "no path found matching pattern" >= 0 then
a30de4
-            raise Not_found
a30de4
-          else
a30de4
-            raise exn in
a30de4
-      if Array.length lines = 0 then
a30de4
-        error (f_"internal error: file_owner: dpkg command returned no output");
a30de4
-      let line = lines.(0) in
a30de4
-      let line =
a30de4
-        try String.sub line 0 (String.rindex line ':')
a30de4
-        with Invalid_argument _ ->
a30de4
-          error (f_"internal error: file_owner: invalid dpkg output: '%s'")
a30de4
-                line in
a30de4
-      fst (String.split "," line)
a30de4
-
a30de4
-  | "rpm" ->
a30de4
-      (* Although it is possible in RPM for multiple packages to own
a30de4
-       * a file, this deliberately only returns one package.
a30de4
-       *)
a30de4
-      let cmd = [| "rpm"; "-qf"; "--qf"; "%{NAME}\\n"; path |] in
a30de4
-      debug "%s" (String.concat " " (Array.to_list cmd));
a30de4
       (try
a30de4
-         let pkgs = g#command_lines cmd in
a30de4
-         pkgs.(0)
a30de4
+         let lines = g#command_lines cmd in
a30de4
+         if Array.length lines = 0 then
a30de4
+           error (f_"internal error: is_file_owned: dpkg command returned no output");
a30de4
+         (* Just check the output looks something like "pkg: filename". *)
a30de4
+         if String.find lines.(0) ": " >= 0 then
a30de4
+           true
a30de4
+         else
a30de4
+           error (f_"internal error: is_file_owned: unexpected output from dpkg command: %s")
a30de4
+                 lines.(0)
a30de4
        with Guestfs.Error msg as exn ->
a30de4
-         if String.find msg "is not owned" >= 0 then
a30de4
-           raise Not_found
a30de4
+         if String.find msg "no path found matching pattern" >= 0 then
a30de4
+           false
a30de4
          else
a30de4
            raise exn
a30de4
-       | Invalid_argument _ (* pkgs.(0) raises index out of bounds *) ->
a30de4
-         error (f_"internal error: file_owner: rpm command returned no output")
a30de4
       )
a30de4
 
a30de4
+  | "rpm" ->
a30de4
+     (* Run rpm -qf and print a magic string if the file is owned.
a30de4
+      * If not owned, rpm will print "... is not owned by any package"
a30de4
+      * and exit with an error.  Unfortunately the string is sent to
a30de4
+      * stdout, so here we ignore the exit status of rpm and just
a30de4
+      * look for one of the two strings.
a30de4
+      *)
a30de4
+     let magic = "FILE_OWNED_TEST" in
a30de4
+     let cmd = sprintf "rpm -qf --qf %s %s 2>&1 ||:"
a30de4
+                       (quote (magic ^ "\n")) (quote path) in
a30de4
+     let r = g#sh cmd in
a30de4
+     if String.find r magic >= 0 then true
a30de4
+     else if String.find r "is not owned" >= 0 then false
a30de4
+     else failwithf "RPM file owned test failed: %s" r
a30de4
+
a30de4
   | format ->
a30de4
     error (f_"don't know how to find file owner using %s") format
a30de4
 
a30de4
-and is_file_owned g inspect path =
a30de4
-  try ignore (file_owner g inspect path); true
a30de4
-  with Not_found -> false
a30de4
-
a30de4
 let is_package_manager_save_file filename =
a30de4
   (* Recognized suffixes of package managers. *)
a30de4
   let suffixes = [ ".dpkg-old"; ".dpkg-new"; ".rpmsave"; ".rpmnew"; ] in
a30de4
diff --git a/v2v/linux.mli b/v2v/linux.mli
a30de4
index 705073644..08146a460 100644
a30de4
--- a/v2v/linux.mli
a30de4
+++ b/v2v/linux.mli
a30de4
@@ -29,9 +29,6 @@ val remove : Guestfs.guestfs -> Types.inspect -> string list -> unit
a30de4
 val file_list_of_package : Guestfs.guestfs -> Types.inspect -> Guestfs.application2 -> string list
a30de4
 (** Return list of files owned by package. *)
a30de4
 
a30de4
-val file_owner : Guestfs.guestfs -> Types.inspect -> string -> string
a30de4
-(** Return the name of the package that owns a file. *)
a30de4
-
a30de4
 val is_file_owned : Guestfs.guestfs -> Types.inspect -> string -> bool
a30de4
 (** Returns true if the file is owned by an installed package. *)
a30de4
 
a30de4
-- 
a30de4
2.14.3
a30de4