[Libguestfs] [PATCH v2 1/3] Add URPMI support.

Richard W.M. Jones rjones at redhat.com
Mon Aug 19 08:43:37 UTC 2013


From: Joseph Wang <joequant at gmail.com>

- RWMJ: Some minor fixes, and update dependencies.
---
 configure.ac              |   7 ++-
 src/.depend               |   2 +
 src/Makefile.am           |   2 +
 src/config.ml.in          |   1 +
 src/supermin_urpmi_rpm.ml | 132 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 src/supermin_urpmi_rpm.ml

diff --git a/configure.ac b/configure.ac
index 0c435ca..c190e2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,11 +68,16 @@ fi
 AM_CONDITIONAL(HAVE_PERLDOC,[test "$perldoc" != "no"])
 
 dnl For yum-rpm handler.
-AC_CHECK_PROG(ZYPPER,[zypper],[zypper],[no])
 AC_CHECK_PROG(YUM,[yum],[yum],[no])
 AC_CHECK_PROG(RPM,[rpm],[rpm],[no])
 AC_CHECK_PROG(YUMDOWNLOADER,[yumdownloader],[yumdownloader],[no])
 
+dnl For Zypper handler.
+AC_CHECK_PROG(ZYPPER,[zypper],[zypper],[no])
+
+dnl For URPMI handler.
+AC_CHECK_PROG(URPMI,[urpmi],[urpmi],[no], [$PATH$PATH_SEPARATOR/usr/sbin])
+
 dnl For Debian handler.
 AC_CHECK_PROG(APTITUDE,[aptitude],[aptitude],[no])
 AC_CHECK_PROG(APT_CACHE,[apt-cache],[apt-cache],[no])
diff --git a/src/.depend b/src/.depend
index 8342f31..c1a9147 100644
--- a/src/.depend
+++ b/src/.depend
@@ -12,6 +12,8 @@ supermin_package_handlers.cmo: supermin_utils.cmi supermin_cmdline.cmi supermin_
 supermin_package_handlers.cmx: supermin_utils.cmx supermin_cmdline.cmx supermin_package_handlers.cmi
 supermin_pacman.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
 supermin_pacman.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
+supermin_urpmi_rpm.cmo: supermin_utils.cmi supermin_package_handlers.cmi supermin_cmdline.cmi config.cmo
+supermin_urpmi_rpm.cmx: supermin_utils.cmx supermin_package_handlers.cmx supermin_cmdline.cmx config.cmx
 supermin_utils.cmi:
 supermin_utils.cmo: supermin_cmdline.cmi supermin_utils.cmi
 supermin_utils.cmx: supermin_cmdline.cmx supermin_utils.cmi
diff --git a/src/Makefile.am b/src/Makefile.am
index b0a6723..fe82000 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,7 @@ EXTRA_DIST = \
 	supermin_package_handlers.mli \
 	supermin_package_handlers.ml \
 	supermin_pacman.ml \
+	supermin_urpmi_rpm.ml \
 	supermin_utils.mli \
 	supermin_utils.ml \
 	supermin_yum_rpm.ml \
@@ -50,6 +51,7 @@ endif
 
 SOURCES += \
 	supermin_yum_rpm.ml \
+	supermin_urpmi_rpm.ml \
 	supermin_debian.ml \
 	supermin_pacman.ml \
 	supermin.ml
diff --git a/src/config.ml.in b/src/config.ml.in
index c3e7672..a814f50 100644
--- a/src/config.ml.in
+++ b/src/config.ml.in
@@ -21,6 +21,7 @@ let package_name = "@PACKAGE_NAME@"
 let package_version = "@PACKAGE_VERSION@"
 let zypper = "@ZYPPER@"
 let yum = "@YUM@"
+let urpmi = "@URPMI@"
 let rpm = "@RPM@"
 let yumdownloader = "@YUMDOWNLOADER@"
 let aptitude = "@APTITUDE@"
diff --git a/src/supermin_urpmi_rpm.ml b/src/supermin_urpmi_rpm.ml
new file mode 100644
index 0000000..a598ef5
--- /dev/null
+++ b/src/supermin_urpmi_rpm.ml
@@ -0,0 +1,132 @@
+(* supermin 4
+ * Copyright (C) 2009-2013 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
+ *)
+
+(* URPMI support. *)
+
+open Unix
+open Printf
+
+open Supermin_package_handlers
+open Supermin_utils
+open Supermin_cmdline
+
+(* Create a temporary directory for use by all the functions in this file. *)
+let tmpdir = tmpdir ()
+
+let urpmi_rpm_detect () =
+  (file_exists "/etc/mageia-release") &&
+    Config.urpmi <> "no" && Config.rpm <> "no"
+
+let urpmi_rpm_init () =
+  if use_installed then
+    failwith "urpmi_rpm driver doesn't support --use-installed"
+
+let urpmi_rpm_resolve_dependencies_and_download names mode =
+  if mode = PkgNamesOnly then (
+    eprintf "supermin: urpmi-rpm: --names-only flag is not implemented\n";
+    exit 1
+  );
+  let cmd = sprintf "urpmq -rd --whatprovides --sources %s"
+    (String.concat " " names) in
+  let lines = run_command_get_lines cmd in
+  (* Return list of package filenames. *)
+  let g x =
+     (Filename.concat tmpdir (Filename.basename x)) in
+  let f x =
+      let cmd = sprintf "curl %s -o %s" x (g x) in
+        run_command cmd in
+  List.iter f lines;
+  let uf res e = if List.mem e res then res else e::res in
+  List.fold_left uf [] (List.map g lines)
+
+let rec urpmi_rpm_list_files pkg =
+  (* Run rpm -qlp with some extra magic. *)
+  let cmd =
+    sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' -p %s"
+      pkg in
+  let lines = run_command_get_lines cmd in
+
+  let files =
+    filter_map (
+      fun line ->
+        match string_split " " line with
+        | [filename; flags; mode; size] ->
+            let test_flag = String.contains flags in
+            let mode = int_of_string mode in
+	    let size = int_of_string size in
+            if test_flag 'd' then None  (* ignore documentation *)
+            else
+              Some (filename, {
+                      ft_dir = mode land 0o40000 <> 0;
+                      ft_ghost = test_flag 'g'; ft_config = test_flag 'c';
+                      ft_mode = mode; ft_size = size;
+                    })
+        | _ ->
+            eprintf "supermin: bad output from rpm command: '%s'" line;
+            exit 1
+    ) lines in
+
+  (* I've never understood why the base packages like 'filesystem' don't
+   * contain any /dev nodes at all.  This leaves every program that
+   * bootstraps RPMs to create a varying set of device nodes themselves.
+   * This collection was copied from mock/backend.py.
+   *)
+  let files =
+    let b = Filename.basename pkg in
+    if string_prefix "filesystem-" b then (
+      let dirs = [ "/proc"; "/sys"; "/dev"; "/dev/pts"; "/dev/shm";
+                   "/dev/mapper" ] in
+      let dirs =
+        List.map (fun name ->
+                    name, { ft_dir = true; ft_ghost = false;
+                            ft_config = false; ft_mode = 0o40755;
+			    ft_size = 0 }) dirs in
+      let devs = [ "/dev/null"; "/dev/full"; "/dev/zero"; "/dev/random";
+                   "/dev/urandom"; "/dev/tty"; "/dev/console";
+                   "/dev/ptmx"; "/dev/stdin"; "/dev/stdout"; "/dev/stderr" ] in
+      (* No need to set the mode because these will go into hostfiles. *)
+      let devs =
+        List.map (fun name ->
+                    name, { ft_dir = false; ft_ghost = false;
+                            ft_config = false; ft_mode = 0o644;
+			    ft_size = 0 }) devs in
+      dirs @ devs @ files
+    ) else files in
+
+  files
+
+let urpmi_rpm_get_file_from_package pkg file =
+  debug "extracting %s from %s ..." file (Filename.basename pkg);
+
+  let outfile = tmpdir // file in
+  let cmd =
+    sprintf "umask 0000; rpm2cpio %s | (cd %s && cpio --quiet -id .%s)"
+      (Filename.quote pkg) (Filename.quote tmpdir) (Filename.quote file) in
+  run_command cmd;
+  outfile
+
+let () =
+  let ph = {
+    ph_detect = urpmi_rpm_detect;
+    ph_init = urpmi_rpm_init;
+    ph_resolve_dependencies_and_download =
+      urpmi_rpm_resolve_dependencies_and_download;
+    ph_list_files = urpmi_rpm_list_files;
+    ph_get_file_from_package = urpmi_rpm_get_file_from_package;
+  } in
+  register_package_handler "urpmi-rpm" ph
-- 
1.8.3.1




More information about the Libguestfs mailing list