[Libguestfs] [PATCH v3 14/22] v2v: linux: Convert the Linux-related conversion modules from Str to PCRE.

Richard W.M. Jones rjones at redhat.com
Fri Sep 22 07:36:15 UTC 2017


For each regular expression I went back to the original Perl code to
ensure that the regexp is correct.
---
 v2v/convert_linux.ml     | 61 +++++++++++++++++-------------------------------
 v2v/linux_bootloaders.ml | 32 ++++++++++++-------------
 v2v/linux_kernels.ml     | 17 +++++++-------
 3 files changed, 46 insertions(+), 64 deletions(-)

diff --git a/v2v/convert_linux.ml b/v2v/convert_linux.ml
index 93a6f1732..df7d4dd14 100644
--- a/v2v/convert_linux.ml
+++ b/v2v/convert_linux.ml
@@ -176,11 +176,11 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
     if g#is_file ~followsymlinks:true vboxconfig then (
       let lines = g#read_lines vboxconfig in
       let lines = Array.to_list lines in
-      let rex = Str.regexp "^INSTALL_DIR=\\(.*\\)$" in
+      let rex = PCRE.compile "^INSTALL_DIR=(.*)$" in
       let lines = filter_map (
         fun line ->
-          if Str.string_match rex line 0 then (
-            let path = Str.matched_group 1 line in
+          if PCRE.matches rex line then (
+            let path = PCRE.sub 1 in
             let path = shell_unquote path in
             if String.length path >= 1 && path.[0] = '/' then (
               let vboxuninstall = path ^ "/uninstall.sh" in
@@ -260,8 +260,7 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
              *)
             if provides <> [] then (
               (* Trim whitespace. *)
-              let rex = Str.regexp "^[ \t]*\\([^ \t]+\\)[ \t]*$" in
-              let provides = List.map (Str.replace_first rex "\\1") provides in
+              let provides = List.map String.trim provides in
 
               (* Install the dependencies with yum.  Use yum explicitly
                * because we don't have package names and local install is
@@ -327,7 +326,7 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
        * ttys in /etc/inittab if the system uses it. We need to put
        * them back.
        *)
-      let rex = Str.regexp "^\\([1-6]\\):\\([2-5]+\\):respawn:\\(.*\\)" in
+      let rex = PCRE.compile "^([1-6]):([2-5]+):respawn:(.*)" in
       let updated = ref false in
       let rec loop () =
         let comments = g#aug_match "/files/etc/inittab/#comment" in
@@ -336,10 +335,10 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
         | [] -> ()
         | commentp :: _ ->
           let comment = g#aug_get commentp in
-          if Str.string_match rex comment 0 then (
-            let name = Str.matched_group 1 comment in
-            let runlevels = Str.matched_group 2 comment in
-            let process = Str.matched_group 3 comment in
+          if PCRE.matches rex comment then (
+            let name = PCRE.sub 1
+            and runlevels = PCRE.sub 2
+            and process = PCRE.sub 3 in
 
             if String.find process "getty" >= 0 then (
               updated := true;
@@ -628,14 +627,12 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
      *)
     let paths = g#aug_match "/files/etc/inittab/*/process" in
     let paths = Array.to_list paths in
-    let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
+    let rex = PCRE.compile "\\b([xh]vc0)\\b" in
     List.iter (
       fun path ->
         let proc = g#aug_get path in
-        if Str.string_match rex proc 0 then (
-          let proc = Str.global_replace rex "\\1ttyS0\\3" proc in
-          g#aug_set path proc
-        );
+        let proc' = PCRE.replace ~global:true rex "ttyS0" proc in
+        if proc <> proc' then g#aug_set path proc'
     ) paths;
 
     let paths = g#aug_match "/files/etc/securetty/*" in
@@ -658,11 +655,11 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
      *)
     let paths = g#aug_match "/files/etc/inittab/*/process" in
     let paths = Array.to_list paths in
-    let rex = Str.regexp ".*\\b\\([xh]vc0|ttyS0\\)\\b.*" in
+    let rex = PCRE.compile "\\b([xh]vc0|ttyS0)\\b" in
     List.iter (
       fun path ->
         let proc = g#aug_get path in
-        if Str.string_match rex proc 0 then
+        if PCRE.matches rex proc then
           ignore (g#aug_rm (path ^ "/.."))
     ) paths;
 
@@ -918,14 +915,8 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
 
     (* Map device names for each entry. *)
     let rex_resume = PCRE.compile "^(.*resume=)(/dev/\\S+)(.*)$"
-    and rex_device_cciss_p =
-      Str.regexp "^/dev/\\(cciss/c[0-9]+d[0-9]+\\)p\\([0-9]+\\)$"
-    and rex_device_cciss =
-      Str.regexp "^/dev/\\(cciss/c[0-9]+d[0-9]+\\)$"
-    and rex_device_p =
-      Str.regexp "^/dev/\\([a-z]+\\)\\([0-9]+\\)$"
-    and rex_device =
-      Str.regexp "^/dev/\\([a-z]+\\)$" in
+    and rex_device_cciss = PCRE.compile "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$"
+    and rex_device = PCRE.compile "^/dev/([a-z]+)(\\d*)?$" in
 
     let rec replace_if_device path value =
       let replace device =
@@ -952,24 +943,16 @@ let rec convert (g : G.guestfs) inspect source output rcaps =
         )
         else value
       )
-      else if Str.string_match rex_device_cciss_p value 0 then (
-        let device = Str.matched_group 1 value
-        and part = Str.matched_group 2 value in
+      else if PCRE.matches rex_device_cciss value then (
+        let device = PCRE.sub 1
+        and part = try PCRE.sub 2 with Not_found -> "" in
         "/dev/" ^ replace device ^ part
       )
-      else if Str.string_match rex_device_cciss value 0 then (
-        let device = Str.matched_group 1 value in
-        "/dev/" ^ replace device
-      )
-      else if Str.string_match rex_device_p value 0 then (
-        let device = Str.matched_group 1 value
-        and part = Str.matched_group 2 value in
+      else if PCRE.matches rex_device value then (
+        let device = PCRE.sub 1
+        and part = try PCRE.sub 2 with Not_found -> "" in
         "/dev/" ^ replace device ^ part
       )
-      else if Str.string_match rex_device value 0 then (
-        let device = Str.matched_group 1 value in
-        "/dev/" ^ replace device
-      )
       else (* doesn't look like a known device name *)
         value
     in
diff --git a/v2v/linux_bootloaders.ml b/v2v/linux_bootloaders.ml
index 00cb5cd19..59af38a86 100644
--- a/v2v/linux_bootloaders.ml
+++ b/v2v/linux_bootloaders.ml
@@ -44,9 +44,9 @@ type bootloader_type =
   | Grub2
 
 (* Helper function for SUSE: remove (hdX,X) prefix from a path. *)
-let remove_hd_prefix path =
-  let rex = Str.regexp "^(hd.*)\\(.*\\)" in
-  Str.replace_first rex "\\1" path
+let remove_hd_prefix =
+  let rex = PCRE.compile "^\\(hd.*\\)" in
+  PCRE.replace rex ""
 
 (* Grub1 (AKA grub-legacy) representation. *)
 class bootloader_grub1 (g : G.guestfs) inspect grub_config =
@@ -132,11 +132,11 @@ object
     if paths = [] then
       error (f_"didn't find grub entry for kernel %s") vmlinuz;
     let path = List.hd paths in
-    let rex = Str.regexp ".*/title\\[\\([1-9][0-9]*\\)\\]/kernel" in
-    if not (Str.string_match rex path 0) then
+    let rex = PCRE.compile "/title(?:\\[(\\d+)\\])?/kernel" in
+    if not (PCRE.matches rex path) then
       error (f_"internal error: regular expression did not match ‘%s’")
         path;
-    let index = int_of_string (Str.matched_group 1 path) - 1 in
+    let index = try int_of_string (PCRE.sub 1) - 1 with Not_found -> 0 in
     g#aug_set (sprintf "/files%s/default" grub_config) (string_of_int index);
     g#aug_save ()
 
@@ -151,7 +151,7 @@ object
     ) else false
 
   method configure_console () =
-    let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
+    let rex = PCRE.compile "\\b([xh]vc0)\\b" in
     let expr = sprintf "/files%s/title/kernel/console" grub_config in
 
     let paths = g#aug_match expr in
@@ -159,23 +159,21 @@ object
     List.iter (
       fun path ->
         let console = g#aug_get path in
-        if Str.string_match rex console 0 then (
-          let console = Str.global_replace rex "\\1ttyS0\\3" console in
-          g#aug_set path console
-        )
+        let console' = PCRE.replace ~global:true rex "ttyS0" console in
+        if console <> console' then g#aug_set path console'
     ) paths;
 
     g#aug_save ()
 
   method remove_console () =
-    let rex = Str.regexp "\\(.*\\)\\b\\([xh]vc0\\)\\b\\(.*\\)" in
+    let rex = PCRE.compile "\\b([xh]vc0)\\b" in
     let expr = sprintf "/files%s/title/kernel/console" grub_config in
 
     let rec loop = function
       | [] -> ()
       | path :: paths ->
         let console = g#aug_get path in
-        if Str.string_match rex console 0 then (
+        if PCRE.matches rex console then (
           ignore (g#aug_rm path);
           (* All the paths are invalid, restart the loop. *)
           let paths = g#aug_match expr in
@@ -231,7 +229,7 @@ object (self)
   inherit bootloader
 
   method private grub2_update_console ~remove () =
-    let rex = Str.regexp "\\(.*\\)\\bconsole=[xh]vc0\\b\\(.*\\)" in
+    let rex = PCRE.compile "\\bconsole=[xh]vc0\\b" in
 
     let paths = [
       "/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX";
@@ -249,12 +247,12 @@ object (self)
         warning (f_"could not remove grub2 serial console (ignored)")
     | path :: _ ->
       let grub_cmdline = g#aug_get path in
-      if Str.string_match rex grub_cmdline 0 then (
+      if PCRE.matches rex grub_cmdline then (
         let new_grub_cmdline =
           if not remove then
-            Str.global_replace rex "\\1console=ttyS0\\2" grub_cmdline
+            PCRE.replace ~global:true rex "console=ttyS0" grub_cmdline
           else
-            Str.global_replace rex "\\1\\2" grub_cmdline in
+            PCRE.replace ~global:true rex "" grub_cmdline in
         g#aug_set path new_grub_cmdline;
         g#aug_save ();
 
diff --git a/v2v/linux_kernels.ml b/v2v/linux_kernels.ml
index 6e1ca4bf1..9853b0029 100644
--- a/v2v/linux_kernels.ml
+++ b/v2v/linux_kernels.ml
@@ -63,10 +63,12 @@ let print_kernel_info chan prefix ki =
   fpf "pvpanic=%b xen=%b debug=%b\n"
       ki.ki_supports_isa_pvpanic ki.ki_is_xen_pv_only_kernel ki.ki_is_debug
 
+let rex_ko = PCRE.compile "\\.k?o(?:\\.xz)?$"
+let rex_ko_extract = PCRE.compile "/([^/]+)\\.k?o(?:\\.xz)?$"
+
 let detect_kernels (g : G.guestfs) inspect family bootloader =
   (* What kernel/kernel-like packages are installed on the current guest? *)
   let installed_kernels : kernel_info list =
-    let rex_ko = Str.regexp ".*\\.k?o\\(\\.xz\\)?$" in
     let check_config feature = function
       | None -> false
       | Some config ->
@@ -82,12 +84,11 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
           | _ -> false
           )
     in
-    let rex_ko_extract = Str.regexp ".*/\\([^/]+\\)\\.k?o\\(\\.xz\\)?$" in
     let rex_initrd =
       if family = `Debian_family then
-        Str.regexp "^initrd.img-.*$"
+        PCRE.compile "^initrd.img-.*$"
       else
-        Str.regexp "^initr\\(d\\|amfs\\)-.*\\(\\.img\\)?$" in
+        PCRE.compile "^initr(?:d|amfs)-.*(?:\\.img)?$" in
     filter_map (
       function
       | { G.app2_name = name } as app
@@ -133,7 +134,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
                let files = g#ls "/boot" in
                let files = Array.to_list files in
                let files =
-                 List.filter (fun n -> Str.string_match rex_initrd n 0) files in
+                 List.filter (fun n -> PCRE.matches rex_initrd n) files in
                let files =
                  List.filter (
                    fun n ->
@@ -165,7 +166,7 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
              let modules = g#find modpath in
              let modules = Array.to_list modules in
              let modules =
-               List.filter (fun m -> Str.string_match rex_ko m 0) modules in
+               List.filter (fun m -> PCRE.matches rex_ko m) modules in
              assert (List.length modules > 0);
 
              (* Determine the kernel architecture by looking at the
@@ -178,8 +179,8 @@ let detect_kernels (g : G.guestfs) inspect family bootloader =
              (* Just return the module names, without path or extension. *)
              let modules = filter_map (
                fun m ->
-                 if Str.string_match rex_ko_extract m 0 then
-                   Some (Str.matched_group 1 m)
+                 if PCRE.matches rex_ko_extract m then
+                   Some (PCRE.sub 1)
                  else
                    None
              ) modules in
-- 
2.13.2




More information about the Libguestfs mailing list