Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for poldek_rpm backend #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ 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 Poldek handler.
AC_CHECK_PROG(POLDEK,[poldek],[poldek],[no])

dnl For Debian handler.
AC_CHECK_PROG(APTITUDE,[aptitude],[aptitude],[no])
AC_CHECK_PROG(APT_CACHE,[apt-cache],[apt-cache],[no])
Expand Down
2 changes: 2 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ EXTRA_DIST = \
supermin_package_handlers.ml \
supermin_pacman.ml \
supermin_urpmi_rpm.ml \
supermin_poldek_rpm.ml \
supermin_utils.mli \
supermin_utils.ml \
supermin_yum_rpm.ml \
Expand All @@ -52,6 +53,7 @@ endif
SOURCES += \
supermin_yum_rpm.ml \
supermin_urpmi_rpm.ml \
supermin_poldek_rpm.ml \
supermin_debian.ml \
supermin_pacman.ml \
supermin.ml
Expand Down
1 change: 1 addition & 0 deletions src/config.ml.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ let package_version = "@PACKAGE_VERSION@"
let zypper = "@ZYPPER@"
let yum = "@YUM@"
let urpmi = "@URPMI@"
let poldek = "@POLDEK@"
let rpm = "@RPM@"
let yumdownloader = "@YUMDOWNLOADER@"
let aptitude = "@APTITUDE@"
Expand Down
184 changes: 184 additions & 0 deletions src/supermin_poldek_rpm.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
(* 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
*)

(* Poldek and RPM 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 poldek_rpm_detect () =
file_exists "/etc/pld-release" &&
Config.poldek <> "no" && Config.rpm <> "no"

let poldek_rpm_init () =
if use_installed then
eprintf "supermin: poldek_rpm driver assumes all packages are already installed when called with option --use-installed.\n%!"

let poldek_rpm_resolve_dependencies_and_download_no_installed names =
(* Liberate this data from shell. *)
let tmp_pkg_cache_dir = tmpdir // "pkg_cache_dir" in
let tmp_root = tmpdir // "root" in
let sh = sprintf "
%s
rpm --root=%s --initdb
install -d %s
poldek --root=%s --fetch=%s %s -u \
$@
"
(if verbose then "set -x" else "")
tmp_root
tmp_pkg_cache_dir
tmp_root
tmp_pkg_cache_dir
(if verbose then "-v" else "-q")
in
run_shell sh names;

(* http://rosettacode.org/wiki/Walk_a_directory/Recursively *)
let walk_directory_tree dir pattern =
let select str = Str.string_match (Str.regexp pattern) str 0 in
let rec walk acc = function
| [] -> (acc)
| dir::tail ->
let contents = Array.to_list (Sys.readdir dir) in
let contents = List.rev_map (Filename.concat dir) contents in
let dirs, files =
List.fold_left (fun (dirs,files) f ->
match (stat f).st_kind with
| S_REG -> (dirs, f::files) (* Regular file *)
| S_DIR -> (f::dirs, files) (* Directory *)
| _ -> (dirs, files)
) ([],[]) contents
in
let matched = List.filter (select) files in
walk (matched @ acc) (dirs @ tail)
in
walk [] [dir]
in

let pkgs = walk_directory_tree tmp_pkg_cache_dir ".*\\.rpm" in

(* Return list of package filenames. *)
pkgs

let poldek_rpm_resolve_dependencies_and_download names mode =
if mode = PkgNamesOnly then (
eprintf "supermin: poldek-rpm: --names-only flag is not implemented\n";
exit 1
);

if use_installed then
(* TODO: try to understand from 9750c2e what should do on use_installed *)
failwith "poldek_rpm driver doesn't support --use-installed"
else
poldek_rpm_resolve_dependencies_and_download_no_installed names

let rec poldek_rpm_list_files pkg =
(* Run rpm -qlp with some extra magic. *)
let cmd =
sprintf "rpm -q --qf '[%%{FILENAMES} %%{FILEFLAGS:fflags} %%{FILEMODES} %%{FILESIZES}\\n]' %s %S"
(if use_installed then "" else "-p")
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 (
(* Skip unreadable files when called as non-root *)
if Unix.getuid() > 0 &&
(try Unix.access filename [Unix.R_OK]; false with
Unix_error _ -> eprintf "supermin: EPERM %s\n%!" filename; true) then None
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 poldek_rpm_get_file_from_package pkg file =
if use_installed then
file
else (
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 = poldek_rpm_detect;
ph_init = poldek_rpm_init;
ph_resolve_dependencies_and_download =
poldek_rpm_resolve_dependencies_and_download;
ph_list_files = poldek_rpm_list_files;
ph_get_file_from_package = poldek_rpm_get_file_from_package;
} in
register_package_handler "poldek" ph