# Copyright (C) 2005 Mandriva # Olivier Blin # Copyright (C) 2017-2018 Mageia # Martin Whitaker # # 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, 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-1335, USA. # SYNOPSIS # -------- # This package provides a function to build the compressed images that will # be mounted as loopback filesystems when booting a Live system. package MGA::DrakISO::BuildLoop; use strict; use MDK::Common; use common; use File::Temp qw(tmpnam); use MGA::DrakISO::LiveBuild; use MGA::DrakISO::Loopback; use MGA::DrakISO::Utils; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(build_live_loopback_files list_loopback_modules); # This is the top-level function called to build the loopback images. The Live # root filesystem must have been prepared before calling this function. # sub build_live_loopback_files { my ($build) = @_; my $root = $build->get_live_root; # make sure no external filesystems are mounted before creating the loopback umount_all_in_root($root); my @excluded_files = expand_file_list($build, @{$build->{loopbacks}{exclude}{files} || []}); my @modules_files = expand_file_list($build, @{$build->{loopbacks}{modules} || []}); foreach (grep { exists $loop_types{$_->{type}}{build} } @{$build->{mount}{dirs} || []}) { local $_->{exclude} = [ @excluded_files, @modules_files ]; $loop_types{$_->{type}}{build}->($build, $_); } foreach my $module (list_loopback_modules($build)) { my $copy_tree = $root . "/tmp/draklive/loop/$module->{name}"; run_as_root('rm', '-rf', $copy_tree); hardlink_filtered($root, $copy_tree, $module->{files}); my $loop = $loop_types{$module->{type}}; $loop->{build}->($build, { path => "/modules/$module->{name}", root => $copy_tree, exclude => \@excluded_files }); run_as_root('rm', '-rf', $copy_tree); } if (@excluded_files) { my $excluded_tree = $root . "/tmp/draklive/excluded/all"; eval { rm_rf($excluded_tree) }; hardlink_filtered($root, $excluded_tree, \@excluded_files); foreach my $module (list_loopback_modules($build)) { my $copy_tree = $root . "/tmp/draklive/excluded/$module->{name}"; run_as_root('rm', '-rf', $copy_tree); hardlink_filtered($excluded_tree, $copy_tree, $module->{files}); my $loop = $loop_types{$module->{type}}; $loop->{build}->($build, { path => "/modules/excluded-$module->{name}", root => $copy_tree }); run_as_root('rm', '-rf', $copy_tree); } my $loop = $loop_types{$build->{loopbacks}{exclude}{type}}; $loop->{build}->($build, { path => "/excluded", root => $excluded_tree, exclude => \@modules_files }); run_as_root('rm', '-rf', $excluded_tree); } } sub expand_file_list { my ($build, @files) = @_; map { $_->{path} ? $_->{path} : chomp_(cat_(glob(($_->{rooted} && $build->get_live_root) . $_->{source}))); } @files; } #- hardlink recursively file list to a directory sub hardlink_filtered { my ($src, $dest, $files) = @_; mkdir_p($dest); my $list_file = tmpnam(); output_p($list_file, map { "$_\n" } grep { -e $src . $_ } @$files); #- cpio -pldm won't copy recursively, use rsync -r instead run_as_root('rsync', '-ar', '--files-from=' . $list_file, '--link-dest=' . $src, $src, $dest); unlink $list_file; } sub list_loopback_modules { my ($build) = @_; map { my $l = $_; map { my $list = $_; my $name = basename($list); $name =~ s/\.[^.]+$//; { type => $l->{type}, name => $name, files => [ expand_file_list($build, { source => $list }) ] }; } glob(($_->{rooted} && $build->get_live_root) . $_->{source}); } @{$build->{loopbacks}{modules}}; } 1;