From aaaeb9f927d17a766cbb143f65e4f1702cbd04ba Mon Sep 17 00:00:00 2001 From: Oliver Tappe Date: Mon, 1 Sep 2008 10:32:02 +0000 Subject: * next refactoring step: made MakeInitRamFS part of boot environment git-svn-id: http://svn.openslx.org/svn/openslx/openslx/trunk@2167 95ad53e4-c205-0410-b2fa-d234c58c8868 --- Makefile | 2 - boot-env/OpenSLX/BootEnvironment/Base.pm | 5 +- boot-env/OpenSLX/MakeInitRamFS/Distro/Base.pm | 48 ++ boot-env/OpenSLX/MakeInitRamFS/Distro/Debian.pm | 57 +++ boot-env/OpenSLX/MakeInitRamFS/Distro/Suse.pm | 59 +++ boot-env/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm | 57 +++ boot-env/OpenSLX/MakeInitRamFS/Engine/Base.pm | 374 ++++++++++++++ boot-env/OpenSLX/MakeInitRamFS/Engine/SlxBoot.pm | 249 +++++++++ initramfs/OpenSLX/LibScanner.pm | 262 ---------- initramfs/OpenSLX/MakeInitRamFS/Distro/Base.pm | 48 -- initramfs/OpenSLX/MakeInitRamFS/Distro/Debian.pm | 57 --- initramfs/OpenSLX/MakeInitRamFS/Distro/Suse.pm | 59 --- initramfs/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm | 57 --- initramfs/OpenSLX/MakeInitRamFS/Engine.pm | 609 ----------------------- lib/OpenSLX/LibScanner.pm | 262 ++++++++++ 15 files changed, 1109 insertions(+), 1096 deletions(-) create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Distro/Base.pm create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Distro/Debian.pm create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Distro/Suse.pm create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Engine/Base.pm create mode 100644 boot-env/OpenSLX/MakeInitRamFS/Engine/SlxBoot.pm delete mode 100644 initramfs/OpenSLX/LibScanner.pm delete mode 100644 initramfs/OpenSLX/MakeInitRamFS/Distro/Base.pm delete mode 100644 initramfs/OpenSLX/MakeInitRamFS/Distro/Debian.pm delete mode 100644 initramfs/OpenSLX/MakeInitRamFS/Distro/Suse.pm delete mode 100644 initramfs/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm delete mode 100644 initramfs/OpenSLX/MakeInitRamFS/Engine.pm create mode 100644 lib/OpenSLX/LibScanner.pm diff --git a/Makefile b/Makefile index ed210afa..b65dc377 100644 --- a/Makefile +++ b/Makefile @@ -160,8 +160,6 @@ supported."; \ | tar -xp -C $(SLX_BUILD_PATH)$(SLX_BASE_PATH)/lib; \ tar --exclude=.svn -cp -C config-db OpenSLX \ | tar -xp -C $(SLX_BUILD_PATH)$(SLX_BASE_PATH)/lib; \ - tar --exclude=.svn -cp -C initramfs OpenSLX \ - | tar -xp -C $(SLX_BUILD_PATH)$(SLX_BASE_PATH)/lib; \ tar --exclude=.svn -cp -C installer OpenSLX \ | tar -xp -C $(SLX_BUILD_PATH)$(SLX_BASE_PATH)/lib; \ tar --exclude=.svn -cp -C os-plugins OpenSLX \ diff --git a/boot-env/OpenSLX/BootEnvironment/Base.pm b/boot-env/OpenSLX/BootEnvironment/Base.pm index 78732957..50969f26 100644 --- a/boot-env/OpenSLX/BootEnvironment/Base.pm +++ b/boot-env/OpenSLX/BootEnvironment/Base.pm @@ -24,7 +24,7 @@ use File::Path; use OpenSLX::Basics; use OpenSLX::ConfigDB; -use OpenSLX::MakeInitRamFS::Engine; +use OpenSLX::MakeInitRamFS::Engine::SlxBoot; use OpenSLX::Utils; our %initramfsMap; @@ -154,7 +154,8 @@ sub _makeInitRamFS $params->{'debug-level'} = $debugLevel; } - my $makeInitRamFSEngine = OpenSLX::MakeInitRamFS::Engine->new($params); + my $makeInitRamFSEngine + = OpenSLX::MakeInitRamFS::Engine::SlxBoot->new($params); $makeInitRamFSEngine->execute($self->{'dry-run'}); # copy back kernel-params, as they might have been changed (by plugins) diff --git a/boot-env/OpenSLX/MakeInitRamFS/Distro/Base.pm b/boot-env/OpenSLX/MakeInitRamFS/Distro/Base.pm new file mode 100644 index 00000000..9be218e8 --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Distro/Base.pm @@ -0,0 +1,48 @@ +# Copyright (c) 2006, 2007 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitRamFS::Distro::Base.pm +# - provides empty base of the distro-specific part of the OpenSLX +# MakeInitRamFS API. +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Distro::Base; + +use strict; +use warnings; + +our $VERSION = 1.01; # API-version . implementation-version + +use OpenSLX::Basics; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'base', + }; + return bless $self, $class; +} + +sub applyChanges +{ +} + +sub determineMatchingHwinfoVersion +{ + my $self = shift; + my $distroVersion = shift; + + return '15.3'; +} + +1; diff --git a/boot-env/OpenSLX/MakeInitRamFS/Distro/Debian.pm b/boot-env/OpenSLX/MakeInitRamFS/Distro/Debian.pm new file mode 100644 index 00000000..30ad4b0d --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Distro/Debian.pm @@ -0,0 +1,57 @@ +# Copyright (c) 2006, 2007 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitRamFS::Distro::Debian.pm +# - provides Debian-specific overrides of the MakeInitRamFS::Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Distro::Debian; + +use strict; +use warnings; + +use base qw(OpenSLX::MakeInitRamFS::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'debian', + }; + return bless $self, $class; +} + +sub applyChanges +{ + my $self = shift; + my $engine = shift; + + $engine->_addFilteredKernelModules( qw( af_packet hid unix )); + + return; +} + +sub determineMatchingHwinfoVersion +{ + my $self = shift; + my $distroVersion = shift; + + # TODO: fill this map (see Suse.pm for an example) + my %versionMap = ( + ); + return $versionMap{$distroVersion} + || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); +} + +1; \ No newline at end of file diff --git a/boot-env/OpenSLX/MakeInitRamFS/Distro/Suse.pm b/boot-env/OpenSLX/MakeInitRamFS/Distro/Suse.pm new file mode 100644 index 00000000..aad790fd --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Distro/Suse.pm @@ -0,0 +1,59 @@ +# Copyright (c) 2006, 2007 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitRamFS::Distro::SUSE.pm +# - provides SUSE-specific overrides of the MakeInitRamFS::Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Distro::Suse; + +use strict; +use warnings; + +use base qw(OpenSLX::MakeInitRamFS::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'suse', + }; + return bless $self, $class; +} + +sub applyChanges +{ + my $self = shift; + my $engine = shift; + + $engine->_addFilteredKernelModules( qw( hid unix )); + + return; +} + +sub determineMatchingHwinfoVersion +{ + my $self = shift; + my $distroVersion = shift; + + my %versionMap = ( + '10.2' => '13.11', + '10.3' => '14.19', + '11.0' => '15.3', + ); + return $versionMap{$distroVersion} + || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); +} + +1; \ No newline at end of file diff --git a/boot-env/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm b/boot-env/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm new file mode 100644 index 00000000..c95ae2d9 --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm @@ -0,0 +1,57 @@ +# Copyright (c) 2006, 2007 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitRamFS::Distro::Ubuntu.pm +# - provides Ubuntu-specific overrides of the MakeInitRamFS::Distro API. +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Distro::Ubuntu; + +use strict; +use warnings; + +use base qw(OpenSLX::MakeInitRamFS::Distro::Base); + +use OpenSLX::Basics; + +################################################################################ +### implementation +################################################################################ +sub new +{ + my $class = shift; + my $self = { + 'base-name' => 'ubuntu', + }; + return bless $self, $class; +} + +sub applyChanges +{ + my $self = shift; + my $engine = shift; + + $engine->_addFilteredKernelModules( qw( unix )); + + return; +} + +sub determineMatchingHwinfoVersion +{ + my $self = shift; + my $distroVersion = shift; + + # TODO: fill this map (see Suse.pm for an example) + my %versionMap = ( + ); + return $versionMap{$distroVersion} + || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); +} + +1; \ No newline at end of file diff --git a/boot-env/OpenSLX/MakeInitRamFS/Engine/Base.pm b/boot-env/OpenSLX/MakeInitRamFS/Engine/Base.pm new file mode 100644 index 00000000..f2834852 --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Engine/Base.pm @@ -0,0 +1,374 @@ +# Copyright (c) 2006-2008 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitialRamFS::Engine::Base.pm +# - provides basic driver engine for MakeInitialRamFS API. +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Engine::Base; + +use strict; +use warnings; + +use File::Basename; +use File::Find; +use File::Path; +use POSIX qw(strftime); + +use OpenSLX::Basics; +use OpenSLX::LibScanner; +use OpenSLX::OSPlugin::Roster; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $params = shift || {}; + + checkParams($params, { + 'attrs' => '!', + 'debug-level' => '?', + 'export-name' => '!', + 'export-uri' => '!', + 'initramfs' => '!', + 'kernel-params' => '!', + 'kernel-version' => '!', + 'plugins' => '!', + 'root-path' => '!', + 'slx-version' => '!', + 'system-name' => '!', + } ); + + my $self = $params; + + $self->{'system-name'} =~ m{^([^\-]+)-([^:\-]+)} + or die "unable to extract distro-info from $self->{'system-name'}!"; + + $self->{'distro-name'} = lc($1); + $self->{'distro-ver'} = $2; + + my $fullDistroName = lc($1) . '-' . $2; + + $self->{distro} = loadDistroModule({ + distroName => $fullDistroName, + distroScope => 'OpenSLX::MakeInitRamFS::Distro', + }); + if (!$self->{distro}) { + die _tr( + 'unable to load any MakeInitRamFS::Distro module for system %s!', + $self->{'system-name'} + ); + } + + $self->{'lib-scanner'} + = OpenSLX::LibScanner->new({ 'root-path' => $self->{'root-path'} }); + + $self->{'suggested-kernel-modules'} = []; + $self->{'filtered-kernel-modules'} = []; + + return bless $self, $class; +} + +sub execute +{ + my $self = shift; + my $dryRun = shift; + + $self->_collectCMDs(); + + vlog(1, _tr("creating initramfs '%s' ...", $self->{'initramfs'})); + $self->_executeCMDs() unless $dryRun; + + return; +} + +sub haveKernelParam +{ + my $self = shift; + my $param = shift; + + return ref $param eq 'Regexp' + ? grep { $_ =~ $param } @{ $self->{'kernel-params'} } + : grep { $_ eq $param } @{ $self->{'kernel-params'} }; +} + +sub addKernelParams +{ + my $self = shift; + + push @{ $self->{'kernel-params'} }, @_; + + return; +} + +sub kernelParams +{ + my $self = shift; + + return @{ $self->{'kernel-params'} }; +} + +sub addKernelModules +{ + my $self = shift; + + push @{ $self->{'suggested-kernel-modules'} }, @_; + + return; +} + +################################################################################ +### implementation methods +################################################################################ +sub _executeCMDs +{ + my $self = shift; + + foreach my $cmd (@{$self->{CMDs}}) { + if (ref($cmd) eq 'HASH') { + vlog(3, "writing $cmd->{file}"); + my $flags = defined $cmd->{mode} ? { mode => $cmd->{mode} } : undef; + spitFile($cmd->{file}, $cmd->{content}, $flags); + } + else { + vlog(3, "executing: $cmd"); + if (slxsystem($cmd)) { + die _tr( + "unable to execute shell-cmd\n\t%s", $cmd + ); + } + } + } + + return; +} + +sub addCMD +{ + my $self = shift; + my $cmd = shift; + + push @{$self->{CMDs}}, $cmd; + + return; +} + +sub _findBinary +{ + my $self = shift; + my $binary = shift; + + my @binDirs = qw( + bin sbin usr/bin usr/sbin usr/local/bin usr/local/sbin usr/bin/X11 + ); + foreach my $binDir (@binDirs) { + my $binPath = "$self->{'root-path'}/$binDir/$binary"; + return $binPath if -f $binPath && -x $binPath; + } + + return; +} + +sub _addFilteredKernelModules +{ + my $self = shift; + + push @{ $self->{'filtered-kernel-modules'} }, @_; + + return; +} + +sub _copyKernelModules +{ + my $self = shift; + + # read modules.dep and use it to determine module dependencies + my $sourcePath = "$self->{'root-path'}/lib/modules/$self->{'kernel-version'}"; + my @modulesDep = slurpFile("$sourcePath/modules.dep") + or die _tr('unable to open %s!', "$sourcePath/modules.dep"); + my (%dependentModules, %modulePath, %modulesToBeCopied); + foreach my $modulesDep (@modulesDep) { + next if $modulesDep !~ m{^(.+?)/([^/]+)\.ko:\s*(.*?)\s*$}; + my $path = $1; + my $module = $2; + my $dependentsList = $3; + my $fullModulePath = "$path/$module.ko"; + $modulePath{$module} = [] if !exists $modulePath{$module}; + push @{$modulePath{$module}}, $fullModulePath; + $dependentModules{$fullModulePath} = [ split ' ', $dependentsList ]; + } + + my $targetPath + = "$self->{'build-path'}/lib/modules/$self->{'kernel-version'}"; + $self->addCMD("mkdir -p $targetPath"); + $self->addCMD("cp -p $sourcePath/modules.* $targetPath/"); + + # add a couple of kernel modules that we expect to be used in stage3 + # (some of these modules do not exist on all distros, so they will be + # filtered out again by the respective distro object): + my @kernelModules = qw( + af_packet unix hid usbhid uhci-hcd ohci-hcd + ); + push @kernelModules, @{ $self->{'suggested-kernel-modules'} }; + + push @kernelModules, split ' ', $self->{attrs}->{ramfs_fsmods}; + push @kernelModules, split ' ', $self->{attrs}->{ramfs_miscmods}; + push @kernelModules, split ' ', $self->{attrs}->{ramfs_nicmods}; + + # a function that determines dependent modules recursively + my $addDependentsSub; + $addDependentsSub = sub { + my $modulePath = shift; + foreach my $dependentModule (@{$dependentModules{$modulePath}}) { + next if $modulesToBeCopied{$dependentModule}; + $modulesToBeCopied{$dependentModule} = 1; + $addDependentsSub->($dependentModule); + } + }; + + # start with the given kernel modules (names) and build a list of all + # required modules + foreach my $kernelModule (@kernelModules) { + if (!$modulePath{$kernelModule}) { + if (! grep { $_ eq $kernelModule } + @{ $self->{'filtered-kernel-modules'} } + ) { + warn _tr( + 'kernel module "%s" not found (in modules.dep)', + $kernelModule + ); + } + } + foreach my $modulePath (@{$modulePath{$kernelModule}}) { + next if $modulesToBeCopied{$modulePath}; + $modulesToBeCopied{$modulePath} = 1; + $addDependentsSub->($modulePath); + } + } + + # copy all the modules that we think are required + foreach my $moduleToBeCopied (sort keys %modulesToBeCopied) { + my $targetDir = "$self->{'build-path'}" . dirname($moduleToBeCopied); + $self->addCMD("mkdir -p $targetDir"); + my $source = followLink( + "$self->{'root-path'}$moduleToBeCopied", $self->{'root-path'} + ); + my $target = "$self->{'build-path'}$moduleToBeCopied"; + $self->addCMD("cp -p --dereference $source $target"); + } + + return; +} + +sub _platformSpecificFileFor +{ + my $self = shift; + my $binary = shift; + + if ($self->{'system-name'} =~ m{64}) { + return $binary . '.x86_64'; + } + return $binary . '.i586'; +} + +sub _writeInitramfsSetup +{ + my $self = shift; + + # generate initramfs-setup file containing attributes that are + # relevant for the initramfs only (before there's a root-FS): + my $initramfsAttrs = { + 'host_name' => 'slx-client', # just to have something at all + 'ramfs_fsmods' => $self->{attrs}->{ramfs_fsmods} || '', + 'ramfs_miscmods' => $self->{attrs}->{ramfs_miscmods} || '', + 'ramfs_nicmods' => $self->{attrs}->{ramfs_nicmods} || '', + 'rootfs' => $self->{'export-uri'} || '', + }; + my $content = "# attributes set by slxconfig-demuxer:\n"; + foreach my $attr (keys %$initramfsAttrs) { + $content .= qq[$attr="$initramfsAttrs->{$attr}"\n]; + } + $self->addCMD( { + file => "$self->{'build-path'}/etc/initramfs-setup", + content => $content + } ); + + return; +} + +sub _writeSlxSystemConf +{ + my $self = shift; + + # generate slxsystem.conf file with variables that are needed + # in stage3 init. + # TODO: either put this stuff into initramfs-setup or find another solution + my $date = strftime("%d.%m.%Y", localtime); + my $slxConf = unshiftHereDoc(<<" End-of-Here"); + slxconf_date=$date + slxconf_kernver=$self->{'kernel-version'} + slxconf_listnwmod="$self->{attrs}->{ramfs_nicmods}" + slxconf_distro_name=$self->{'distro-name'} + slxconf_distro_ver=$self->{'distro-ver'} + slxconf_system_name=$self->{'system-name'} + slxconf_slxver="$self->{'slx-version'}" + End-of-Here + $self->addCMD( { + file => "$self->{'build-path'}/etc/slxsystem.conf", + content => $slxConf + } ); + + return; +} + +sub _calloutToPlugins +{ + my $self = shift; + + my $pluginInitdPath = "$self->{'build-path'}/etc/plugin-init.d"; + my $initHooksPath = "$self->{'build-path'}/etc/init-hooks"; + $self->addCMD("mkdir -p $pluginInitdPath $initHooksPath"); + + foreach my $pluginName (@{$self->{'plugins'}}) { + my $plugin = OpenSLX::OSPlugin::Roster->getPlugin($pluginName); + next if !$plugin; + + # create a hash only containing the attributes relating to the + # current plugin + my $allAttrs = $self->{attrs}; + my %pluginAttrs; + for my $attrName (grep { $_ =~ m{^${pluginName}::} } keys %$allAttrs) { + $pluginAttrs{$attrName} = $allAttrs->{$attrName}; + } + + # let plugin setup itself in the initramfs + $plugin->setupPluginInInitramfs(\%pluginAttrs, $self); + } + return; +} + +sub _createInitRamFS +{ + my $self = shift; + + my $buildPath = $self->{'build-path'}; + $self->addCMD( + "cd $buildPath " + . "&& find . " + . "| cpio -H newc --quiet --create " + . "| gzip -9 >$self->{initramfs}" + ); + + return; +} + +1; diff --git a/boot-env/OpenSLX/MakeInitRamFS/Engine/SlxBoot.pm b/boot-env/OpenSLX/MakeInitRamFS/Engine/SlxBoot.pm new file mode 100644 index 00000000..a10384b8 --- /dev/null +++ b/boot-env/OpenSLX/MakeInitRamFS/Engine/SlxBoot.pm @@ -0,0 +1,249 @@ +# Copyright (c) 2006-2008 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# MakeInitialRamFS::Engine::SlxBoot.pm +# - provides driver engine for MakeInitialRamFS API, implementing the +# standard slx boot behaviour (i.e. booting a system remotely). +# ----------------------------------------------------------------------------- +package OpenSLX::MakeInitRamFS::Engine::SlxBoot; + +use strict; +use warnings; + +use base qw(OpenSLX::MakeInitRamFS::Engine::Base); + +use File::Basename; +use File::Find; +use File::Path; +use POSIX qw(strftime); + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### implementation methods +################################################################################ +sub _collectCMDs +{ + my $self = shift; + + $self->{CMDs} = []; + + $self->_setupBuildPath(); + + $self->_addRequiredFSMods(); + + $self->_writeInitramfsSetup(); + $self->_writeSlxSystemConf(); + + $self->_copyUclibcRootfs(); + $self->_copyHwinfo(); + $self->_copyDistroSpecificFiles(); + $self->_copyInitramfsFiles(); + + $self->_copyPreAndPostinitFiles(); + + $self->_calloutToPlugins(); + + $self->{distro}->applyChanges($self); + + $self->_copyKernelModules(); + + $self->_createInitRamFS(); + + return; +} + +sub _setupBuildPath +{ + my $self = shift; + + my $buildPath = "$openslxConfig{'temp-path'}/slx-initramfs"; + $self->addCMD("rm -rf $buildPath"); + + my @stdFolders = qw( + bin + dev + etc + etc/init-hooks + lib + mnt + proc + root + sys + tmp + usr/share + var/lib + var/lib/nfs/state + var/run + ); + $self->addCMD( + 'mkdir -p ' . join(' ', map { "$buildPath/$_"; } @stdFolders) + ); + $self->addCMD("ln -sfn /bin $buildPath/sbin"); + + $self->{'build-path'} = $buildPath; + + return; +} + +sub _copyDistroSpecificFiles +{ + my $self = shift; + + my $distroSpecsPath = "$openslxConfig{'base-path'}/share/distro-specs"; + + my $distroName = $self->{'distro-name'}; + my $distroVer = $self->{'distro-ver'}; + + # concatenate default- and distro-specific functions into one file + my $functions = slurpFile("$distroSpecsPath/$distroName/functions-default"); + $functions .= "\n"; + $functions .= slurpFile( + "$distroSpecsPath/$distroName/functions-$distroVer", + { failIfMissing => 0 } + ); + $self->addCMD( { + file => "$self->{'build-path'}/etc/distro-functions", + content => $functions, + } ); + + return 1; +} + +sub _copyUclibcRootfs +{ + my $self = shift; + + my $uclibcRootfs = "$openslxConfig{'base-path'}/share/uclib-rootfs"; + + $self->addCMD("rsync -rlpt $uclibcRootfs/ $self->{'build-path'}"); + + return 1; +} + +sub _copyHwinfo +{ + my $self = shift; + + my $baseDir = "$openslxConfig{'base-path'}/share/ramfstools/hwinfo"; + + my $version = $self->{distro}->determineMatchingHwinfoVersion( + $self->{'distro-ver'} + ); + + $self->addCMD("cp $baseDir/bin/hwinfo-$version $self->{'build-path'}/usr/bin/hwinfo"); + my $libHD = "libhd.so.$version"; + $self->addCMD("cp $baseDir/lib/$libHD $self->{'build-path'}/usr/lib"); + my $libName = $libHD; + while($libName =~ s{\.\d+$}{}g) { + $self->addCMD("ln -sf $libHD $self->{'build-path'}/usr/lib/$libName"); + } + + return 1; +} + +sub _copyInitramfsFiles +{ + my $self = shift; + + my $initramfsPath = "$openslxConfig{'base-path'}/share/initramfs"; + + find( + { + wanted => sub { + my $len = length($initramfsPath); + my $file = $File::Find::name; + my $relName = length($file) > $len ? substr($file, $len+1) : ''; + if (-d) { + $self->addCMD("mkdir -p $self->{'build-path'}/$relName"); + } elsif (-l $file) { + my $target = readlink $file; + $self->addCMD( + "ln -sf $target $self->{'build-path'}/$relName" + ); + } elsif (qx{file $file} =~ m{ELF}) { + $self->addCMD( + "cp -p $file $self->{'build-path'}/$relName" + ); + } else { + my $text = slurpFile($file, { 'io-layer' => 'bytes' } ); + + # replace macros + # TODO: find out what these mean and maybe find a + # different, better solution + my %macro = ( + 'COMDIRINDXS' => '/tmp/scratch /var/lib/nobody', + # keep serverip as it is (it is handled by init itself) + 'serverip' => '@@@serverip@@@', + ); + $text =~ s{\@\@\@([^\@]+)\@\@\@}{ + if (!exists $macro{$1}) { + warn _tr( + 'unknown macro @@@%s@@@ found in %s', + $1, $File::Find::name + ); + ''; + } else { + $macro{$1}; + } + }eogms; + + # force shebang with ash + $text =~ s{\A#!\s*/bin/.+?$}{#!/bin/ash}ms; + + $self->addCMD( { + file => "$self->{'build-path'}/$relName", + content => $text, + mode => (-x $file ? 0755 : undef), + } ); + } + }, + no_chdir => 1, + }, + $initramfsPath + ); + + return; +} + +sub _copyPreAndPostinitFiles +{ + my $self = shift; + + foreach my $cfg ( + 'default/initramfs/preinit.local', + "$self->{'system-name'}/initramfs/preinit.local", + 'default/initramfs/postinit.local', + "$self->{'system-name'}/initramfs/postinit.local" + ) { + my $cfgPath = "$openslxConfig{'private-path'}/config/$cfg"; + next if !-f $cfgPath; + $self->addCMD("cp -p $cfgPath $self->{'build-path'}/bin/"); + } + return; +} + +sub _addRequiredFSMods +{ + my $self = shift; + + my $osExportEngine = instantiateClass("OpenSLX::OSExport::Engine"); + $osExportEngine->initializeFromExisting($self->{'export-name'}); + my $fsMods = $self->{attrs}->{ramfs_fsmods} || ''; + foreach my $fsMod ($osExportEngine->requiredFSMods()) { + $fsMods .= " $fsMod" if $fsMods !~ m{$fsMod}; + } + $self->{attrs}->{ramfs_fsmods} = $fsMods; + + return; +} + +1; diff --git a/initramfs/OpenSLX/LibScanner.pm b/initramfs/OpenSLX/LibScanner.pm deleted file mode 100644 index e1f42ba4..00000000 --- a/initramfs/OpenSLX/LibScanner.pm +++ /dev/null @@ -1,262 +0,0 @@ -# Copyright (c) 2006-2008 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# LibScanner.pm -# - module that recursively scans a given binary for library dependencies -# ----------------------------------------------------------------------------- -package OpenSLX::LibScanner; - -use strict; -use warnings; - -use File::Find; -use File::Path; - -use OpenSLX::Basics; -use OpenSLX::Utils; - -################################################################################ -### interface methods -################################################################################ -sub new -{ - my $class = shift; - my $params = shift || {}; - - checkParams($params, { - 'root-path' => '!', - 'verbose' => '?', - } ); - - my $self = { - rootPath => $params->{'root-path'}, - verbose => $params->{'verbose'} || 0, - }; - - return bless $self, $class; -} - -sub determineRequiredLibs -{ - my $self = shift; - my @binaries = @_; - - $self->{filesToDo} = []; - $self->{libs} = []; - $self->{libInfo} = {}; - - $self->_fetchLoaderConfig(); - - foreach my $binary (@binaries) { - if (substr($binary, 0, 1) ne '/') { - # force relative paths relative to $rootPath: - $binary = "$self->{rootPath}/$binary"; - } - if (!-e $binary) { - warn _tr("$0: unable to find file '%s', skipping it\n", $binary); - next; - } - push @{$self->{filesToDo}}, $binary; - } - - foreach my $file (@{$self->{filesToDo}}) { - $self->_addLibsForBinary($file); - } - - return @{$self->{libs}}; -} - -sub _fetchLoaderConfig -{ - my $self = shift; - - my @libFolders; - - if (!-e "$self->{rootPath}/etc") { - die _tr("'%s'-folder not found, maybe wrong root-path?\n", - "$self->{rootPath}/etc"); - } - $self->_fetchLoaderConfigFile("$self->{rootPath}/etc/ld.so.conf"); - - # add "trusted" folders /lib and /usr/lib if not already in place: - if (!grep { m[^$self->{rootPath}/lib$] } @libFolders) { - push @libFolders, "$self->{rootPath}/lib"; - } - if (!grep { m[^$self->{rootPath}/usr/lib$] } @libFolders) { - push @libFolders, "$self->{rootPath}/usr/lib"; - } - - # add lib32-folders for 64-bit Debians, as they do not - # refer those in ld.so.conf (which I find strange...) - if (-e '/lib32' && !grep { m[^$self->{rootPath}/lib32$] } @libFolders) { - push @libFolders, "$self->{rootPath}/lib32"; - } - if (-e '/usr/lib32' - && !grep { m[^$self->{rootPath}/usr/lib32$] } @libFolders) - { - push @libFolders, "$self->{rootPath}/usr/lib32"; - } - - push @{$self->{libFolders}}, @libFolders; - - return; -} - -sub _fetchLoaderConfigFile -{ - my $self = shift; - my $ldConfFile = shift; - - return unless -e $ldConfFile; - my $ldconfFH; - if (!open($ldconfFH, '<', $ldConfFile)) { - warn(_tr("unable to open file '%s' (%s)", $ldConfFile, $!)); - return; - } - while (<$ldconfFH>) { - chomp; - if (m{^\s*include\s+(.+?)\s*$}i) { - my @incFiles = glob("$self->{rootPath}$1"); - foreach my $incFile (@incFiles) { - if ($incFile) { - $self->_fetchLoaderConfigFile($incFile); - } - } - next; - } - if (m{\S+}i) { - s[=.+][]; - # remove any lib-type specifications (e.g. '=libc5') - push @{$self->{libFolders}}, "$self->{rootPath}$_"; - } - } - close $ldconfFH - or die(_tr("unable to close file '%s' (%s)", $ldConfFile, $!)); - return; -} - -sub _addLibsForBinary -{ - my $self = shift; - my $binary = shift; - - # first do some checks: - warn _tr("analyzing '%s'...\n", $binary) if $self->{verbose}; - my $fileInfo = `file --dereference --brief --mime $binary 2>/dev/null`; - if ($?) { - die _tr("unable to fetch file info for '%s', giving up!\n", $binary); - } - chomp $fileInfo; - warn _tr("\tinfo is: '%s'...\n", $fileInfo) if $self->{verbose}; - if ($fileInfo !~ m[^application/(x-executable|x-shared)]i) { - # ignore anything that's not an executable or a shared library - warn _tr( - "%s: ignored, as it isn't an executable or a shared library\n", - $binary - ); - next; - } - - # fetch file info again, this time without '--mime' in order to get the architecture - # bitwidth: - $fileInfo = `file --dereference --brief $binary 2>/dev/null`; - if ($?) { - die _tr("unable to fetch file info for '%s', giving up!\n", $binary); - } - chomp $fileInfo; - warn _tr("\tinfo is: '%s'...\n", $fileInfo) if $self->{verbose}; - my $bitwidth = ($fileInfo =~ m[64-bit]i) ? 64 : 32; - # determine whether binary is 32- or 64-bit platform - - # now find out about needed libs, we first try objdump... - warn _tr("\ttrying objdump...\n") if $self->{verbose}; - my $res = `objdump -p $binary 2>/dev/null`; - if (!$?) { - # find out if rpath is set for binary: - my $rpath; - if ($res =~ m[^\s*RPATH\s*(\S+)]im) { - $rpath = $1; - warn _tr("\trpath='%s'\n", $rpath) if $self->{verbose}; - } - while ($res =~ m[^\s*NEEDED\s*(.+?)\s*$]gm) { - $self->_addLib($1, $bitwidth, $rpath); - } - } else { - # ...objdump failed, so we try readelf instead: - warn _tr("\ttrying readelf...\n") if $self->{verbose}; - $res = `readelf -d $binary 2>/dev/null`; - if ($?) { - die _tr( - "neither objdump nor readelf seems to be installed, giving up!\n" - ); - } - # find out if rpath is set for binary: - my $rpath; - if ($res =~ m{Library\s*rpath:\s*\[([^\]]+)}im) { - $rpath = $1; - warn _tr("\trpath='%s'\n", $rpath) if $self->{verbose}; - } - while ($res =~ m{\(NEEDED\)[^\[]+\[(.+?)\]\s*$}gm) { - $self->_addLib($1, $bitwidth, $rpath); - } - } - return; -} - -sub _addLib -{ - my $self = shift; - my $lib = shift; - my $bitwidth = shift; - my $rpath = shift; - - if (!exists $self->{libInfo}->{$lib}) { - my $libPath; - my @folders = @{$self->{libFolders}}; - if (defined $rpath) { - # add rpath if given (explicit paths set during link stage) - push @folders, split ':', $rpath; - } - foreach my $folder (@folders) { - if (-e "$folder/$lib") { - # have library matching name, now check if the platform is ok, too: - my $libFileInfo = - `file --dereference --brief $folder/$lib 2>/dev/null`; - if ($?) { - die _tr("unable to fetch file info for '%s', giving up!\n", - $folder / $lib); - } - my $libBitwidth = ($libFileInfo =~ m[64-bit]i) ? 64 : 32; - if ($bitwidth != $libBitwidth) { - vlog( - 0, - _tr( - '%s has wrong bitwidth (%s instead of %s)', - "$folder/$lib", $libBitwidth, $bitwidth - ) - ) if $self->{verbose}; - next; - } - $libPath = "$folder/$lib"; - last; - } - } - if (!defined $libPath) { - die _tr("unable to find lib %s!\n", $lib); - } - print "found $libPath\n" if $self->{verbose}; - push @{$self->{libs}}, $libPath; - $self->{libInfo}->{$lib} = 1; - push @{$self->{filesToDo}}, $libPath; - } - return; -} - -1; diff --git a/initramfs/OpenSLX/MakeInitRamFS/Distro/Base.pm b/initramfs/OpenSLX/MakeInitRamFS/Distro/Base.pm deleted file mode 100644 index 9a7e4966..00000000 --- a/initramfs/OpenSLX/MakeInitRamFS/Distro/Base.pm +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2006, 2007 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# MakeInitRamFS::Base.pm -# - provides empty base of the distro-specific part of the OpenSLX -# MakeInitRamFS API. -# ----------------------------------------------------------------------------- -package OpenSLX::MakeInitRamFS::Distro::Base; - -use strict; -use warnings; - -our $VERSION = 1.01; # API-version . implementation-version - -use OpenSLX::Basics; - -################################################################################ -### interface methods -################################################################################ -sub new -{ - my $class = shift; - my $self = { - 'base-name' => 'base', - }; - return bless $self, $class; -} - -sub applyChanges -{ -} - -sub determineMatchingHwinfoVersion -{ - my $self = shift; - my $distroVersion = shift; - - return '15.3'; -} - -1; diff --git a/initramfs/OpenSLX/MakeInitRamFS/Distro/Debian.pm b/initramfs/OpenSLX/MakeInitRamFS/Distro/Debian.pm deleted file mode 100644 index 30ad4b0d..00000000 --- a/initramfs/OpenSLX/MakeInitRamFS/Distro/Debian.pm +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2006, 2007 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# MakeInitRamFS::Distro::Debian.pm -# - provides Debian-specific overrides of the MakeInitRamFS::Distro API. -# ----------------------------------------------------------------------------- -package OpenSLX::MakeInitRamFS::Distro::Debian; - -use strict; -use warnings; - -use base qw(OpenSLX::MakeInitRamFS::Distro::Base); - -use OpenSLX::Basics; - -################################################################################ -### implementation -################################################################################ -sub new -{ - my $class = shift; - my $self = { - 'base-name' => 'debian', - }; - return bless $self, $class; -} - -sub applyChanges -{ - my $self = shift; - my $engine = shift; - - $engine->_addFilteredKernelModules( qw( af_packet hid unix )); - - return; -} - -sub determineMatchingHwinfoVersion -{ - my $self = shift; - my $distroVersion = shift; - - # TODO: fill this map (see Suse.pm for an example) - my %versionMap = ( - ); - return $versionMap{$distroVersion} - || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); -} - -1; \ No newline at end of file diff --git a/initramfs/OpenSLX/MakeInitRamFS/Distro/Suse.pm b/initramfs/OpenSLX/MakeInitRamFS/Distro/Suse.pm deleted file mode 100644 index aad790fd..00000000 --- a/initramfs/OpenSLX/MakeInitRamFS/Distro/Suse.pm +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (c) 2006, 2007 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# MakeInitRamFS::Distro::SUSE.pm -# - provides SUSE-specific overrides of the MakeInitRamFS::Distro API. -# ----------------------------------------------------------------------------- -package OpenSLX::MakeInitRamFS::Distro::Suse; - -use strict; -use warnings; - -use base qw(OpenSLX::MakeInitRamFS::Distro::Base); - -use OpenSLX::Basics; - -################################################################################ -### implementation -################################################################################ -sub new -{ - my $class = shift; - my $self = { - 'base-name' => 'suse', - }; - return bless $self, $class; -} - -sub applyChanges -{ - my $self = shift; - my $engine = shift; - - $engine->_addFilteredKernelModules( qw( hid unix )); - - return; -} - -sub determineMatchingHwinfoVersion -{ - my $self = shift; - my $distroVersion = shift; - - my %versionMap = ( - '10.2' => '13.11', - '10.3' => '14.19', - '11.0' => '15.3', - ); - return $versionMap{$distroVersion} - || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); -} - -1; \ No newline at end of file diff --git a/initramfs/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm b/initramfs/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm deleted file mode 100644 index c95ae2d9..00000000 --- a/initramfs/OpenSLX/MakeInitRamFS/Distro/Ubuntu.pm +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2006, 2007 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# MakeInitRamFS::Distro::Ubuntu.pm -# - provides Ubuntu-specific overrides of the MakeInitRamFS::Distro API. -# ----------------------------------------------------------------------------- -package OpenSLX::MakeInitRamFS::Distro::Ubuntu; - -use strict; -use warnings; - -use base qw(OpenSLX::MakeInitRamFS::Distro::Base); - -use OpenSLX::Basics; - -################################################################################ -### implementation -################################################################################ -sub new -{ - my $class = shift; - my $self = { - 'base-name' => 'ubuntu', - }; - return bless $self, $class; -} - -sub applyChanges -{ - my $self = shift; - my $engine = shift; - - $engine->_addFilteredKernelModules( qw( unix )); - - return; -} - -sub determineMatchingHwinfoVersion -{ - my $self = shift; - my $distroVersion = shift; - - # TODO: fill this map (see Suse.pm for an example) - my %versionMap = ( - ); - return $versionMap{$distroVersion} - || $self->SUPER::determineMatchingHwinfoVersion($distroVersion); -} - -1; \ No newline at end of file diff --git a/initramfs/OpenSLX/MakeInitRamFS/Engine.pm b/initramfs/OpenSLX/MakeInitRamFS/Engine.pm deleted file mode 100644 index 0defe111..00000000 --- a/initramfs/OpenSLX/MakeInitRamFS/Engine.pm +++ /dev/null @@ -1,609 +0,0 @@ -# Copyright (c) 2006, 2007 - OpenSLX GmbH -# -# This program is free software distributed under the GPL version 2. -# See http://openslx.org/COPYING -# -# If you have any feedback please consult http://openslx.org/feedback and -# send your suggestions, praise, or complaints to feedback@openslx.org -# -# General information about OpenSLX can be found at http://openslx.org/ -# ----------------------------------------------------------------------------- -# MakeInitialRamFS::Engine.pm -# - provides driver engine for MakeInitialRamFS API. -# ----------------------------------------------------------------------------- -package OpenSLX::MakeInitRamFS::Engine; - -use strict; -use warnings; - -use File::Basename; -use File::Find; -use File::Path; -use POSIX qw(strftime); - -use OpenSLX::Basics; -use OpenSLX::LibScanner; -use OpenSLX::OSPlugin::Roster; -use OpenSLX::Utils; - -# TODO: implement support for the following (either here or as plugin): -# wlan -# tpm - -################################################################################ -### interface methods -################################################################################ -sub new -{ - my $class = shift; - my $params = shift || {}; - - checkParams($params, { - 'attrs' => '!', - 'debug-level' => '?', - 'export-name' => '!', - 'export-uri' => '!', - 'initramfs' => '!', - 'kernel-params' => '!', - 'kernel-version' => '!', - 'plugins' => '!', - 'root-path' => '!', - 'slx-version' => '!', - 'system-name' => '!', - } ); - - my $self = $params; - - $self->{'system-name'} =~ m{^([^\-]+)-([^:\-]+)} - or die "unable to extract distro-info from $self->{'system-name'}!"; - - $self->{'distro-name'} = lc($1); - $self->{'distro-ver'} = $2; - - my $fullDistroName = lc($1) . '-' . $2; - - $self->{distro} = loadDistroModule({ - distroName => $fullDistroName, - distroScope => 'OpenSLX::MakeInitRamFS::Distro', - }); - if (!$self->{distro}) { - die _tr( - 'unable to load any MakeInitRamFS::Distro module for system %s!', - $self->{'system-name'} - ); - } - - $self->{'lib-scanner'} - = OpenSLX::LibScanner->new({ 'root-path' => $self->{'root-path'} }); - - $self->{'suggested-kernel-modules'} = []; - $self->{'filtered-kernel-modules'} = []; - - return bless $self, $class; -} - -sub execute -{ - my $self = shift; - my $dryRun = shift; - - $self->_collectCMDs(); - - vlog(1, _tr("creating initramfs '%s' ...", $self->{'initramfs'})); - $self->_executeCMDs() unless $dryRun; - - return; -} - -sub haveKernelParam -{ - my $self = shift; - my $param = shift; - - return ref $param eq 'Regexp' - ? grep { $_ =~ $param } @{ $self->{'kernel-params'} } - : grep { $_ eq $param } @{ $self->{'kernel-params'} }; -} - -sub addKernelParams -{ - my $self = shift; - - push @{ $self->{'kernel-params'} }, @_; - - return; -} - -sub kernelParams -{ - my $self = shift; - - return @{ $self->{'kernel-params'} }; -} - -sub addKernelModules -{ - my $self = shift; - - push @{ $self->{'suggested-kernel-modules'} }, @_; - - return; -} - -################################################################################ -### implementation methods -################################################################################ -sub _collectCMDs -{ - my $self = shift; - - $self->{CMDs} = []; - - $self->_setupBuildPath(); - - $self->_addRequiredFSMods(); - - $self->_writeInitramfsSetup(); - $self->_writeSlxSystemConf(); - - $self->_copyUclibcRootfs(); - $self->_copyHwinfo(); - $self->_copyDistroSpecificFiles(); - $self->_copyInitramfsFiles(); - - $self->_copyPreAndPostinitFiles(); - - $self->_calloutToPlugins(); - - $self->{distro}->applyChanges($self); - - $self->_copyKernelModules(); - - $self->_createInitRamFS(); - - return; -} - -sub _executeCMDs -{ - my $self = shift; - - foreach my $cmd (@{$self->{CMDs}}) { - if (ref($cmd) eq 'HASH') { - vlog(3, "writing $cmd->{file}"); - my $flags = defined $cmd->{mode} ? { mode => $cmd->{mode} } : undef; - spitFile($cmd->{file}, $cmd->{content}, $flags); - } - else { - vlog(3, "executing: $cmd"); - if (slxsystem($cmd)) { - die _tr( - "unable to execute shell-cmd\n\t%s", $cmd - ); - } - } - } - - return; -} - -sub addCMD -{ - my $self = shift; - my $cmd = shift; - - push @{$self->{CMDs}}, $cmd; - - return; -} - -sub _setupBuildPath -{ - my $self = shift; - - my $buildPath = "$openslxConfig{'temp-path'}/slx-initramfs"; - $self->addCMD("rm -rf $buildPath"); - - my @stdFolders = qw( - bin - dev - etc - etc/init-hooks - lib - mnt - proc - root - sys - tmp - usr/share - var/lib - var/lib/nfs/state - var/run - ); - $self->addCMD( - 'mkdir -p ' . join(' ', map { "$buildPath/$_"; } @stdFolders) - ); - $self->addCMD("ln -sfn /bin $buildPath/sbin"); - - $self->{'build-path'} = $buildPath; - - return; -} - -sub _copyDistroSpecificFiles -{ - my $self = shift; - - my $distroSpecsPath = "$openslxConfig{'base-path'}/share/distro-specs"; - - my $distroName = $self->{'distro-name'}; - my $distroVer = $self->{'distro-ver'}; - - # concatenate default- and distro-specific functions into one file - my $functions = slurpFile("$distroSpecsPath/$distroName/functions-default"); - $functions .= "\n"; - $functions .= slurpFile( - "$distroSpecsPath/$distroName/functions-$distroVer", - { failIfMissing => 0 } - ); - $self->addCMD( { - file => "$self->{'build-path'}/etc/distro-functions", - content => $functions, - } ); - - return 1; -} - -sub _copyUclibcRootfs -{ - my $self = shift; - - my $uclibcRootfs = "$openslxConfig{'base-path'}/share/uclib-rootfs"; - - $self->addCMD("rsync -rlpt $uclibcRootfs/ $self->{'build-path'}"); - - return 1; -} - -sub _copyHwinfo -{ - my $self = shift; - - my $baseDir = "$openslxConfig{'base-path'}/share/ramfstools/hwinfo"; - - my $version = $self->{distro}->determineMatchingHwinfoVersion( - $self->{'distro-ver'} - ); - - $self->addCMD("cp $baseDir/bin/hwinfo-$version $self->{'build-path'}/usr/bin/hwinfo"); - my $libHD = "libhd.so.$version"; - $self->addCMD("cp $baseDir/lib/$libHD $self->{'build-path'}/usr/lib"); - my $libName = $libHD; - while($libName =~ s{\.\d+$}{}g) { - $self->addCMD("ln -sf $libHD $self->{'build-path'}/usr/lib/$libName"); - } - - return 1; -} - -sub _copyInitramfsFiles -{ - my $self = shift; - - my $initramfsPath = "$openslxConfig{'base-path'}/share/initramfs"; - - find( - { - wanted => sub { - my $len = length($initramfsPath); - my $file = $File::Find::name; - my $relName = length($file) > $len ? substr($file, $len+1) : ''; - if (-d) { - $self->addCMD("mkdir -p $self->{'build-path'}/$relName"); - } elsif (-l $file) { - my $target = readlink $file; - $self->addCMD( - "ln -sf $target $self->{'build-path'}/$relName" - ); - } elsif (qx{file $file} =~ m{ELF}) { - $self->addCMD( - "cp -p $file $self->{'build-path'}/$relName" - ); - } else { - my $text = slurpFile($file, { 'io-layer' => 'bytes' } ); - - # replace macros - # TODO: find out what these mean and maybe find a - # different, better solution - my %macro = ( - 'COMDIRINDXS' => '/tmp/scratch /var/lib/nobody', - # keep serverip as it is (it is handled by init itself) - 'serverip' => '@@@serverip@@@', - ); - $text =~ s{\@\@\@([^\@]+)\@\@\@}{ - if (!exists $macro{$1}) { - warn _tr( - 'unknown macro @@@%s@@@ found in %s', - $1, $File::Find::name - ); - ''; - } else { - $macro{$1}; - } - }eogms; - - # force shebang with ash - $text =~ s{\A#!\s*/bin/.+?$}{#!/bin/ash}ms; - - $self->addCMD( { - file => "$self->{'build-path'}/$relName", - content => $text, - mode => (-x $file ? 0755 : undef), - } ); - } - }, - no_chdir => 1, - }, - $initramfsPath - ); - - return; -} - -sub _findBinary -{ - my $self = shift; - my $binary = shift; - - my @binDirs = qw( - bin sbin usr/bin usr/sbin usr/local/bin usr/local/sbin usr/bin/X11 - ); - foreach my $binDir (@binDirs) { - my $binPath = "$self->{'root-path'}/$binDir/$binary"; - return $binPath if -f $binPath && -x $binPath; - } - - return; -} - -sub _addFilteredKernelModules -{ - my $self = shift; - - push @{ $self->{'filtered-kernel-modules'} }, @_; - - return; -} - -sub _copyKernelModules -{ - my $self = shift; - - # read modules.dep and use it to determine module dependencies - my $sourcePath = "$self->{'root-path'}/lib/modules/$self->{'kernel-version'}"; - my @modulesDep = slurpFile("$sourcePath/modules.dep") - or die _tr('unable to open %s!', "$sourcePath/modules.dep"); - my (%dependentModules, %modulePath, %modulesToBeCopied); - foreach my $modulesDep (@modulesDep) { - next if $modulesDep !~ m{^(.+?)/([^/]+)\.ko:\s*(.*?)\s*$}; - my $path = $1; - my $module = $2; - my $dependentsList = $3; - my $fullModulePath = "$path/$module.ko"; - $modulePath{$module} = [] if !exists $modulePath{$module}; - push @{$modulePath{$module}}, $fullModulePath; - $dependentModules{$fullModulePath} = [ split ' ', $dependentsList ]; - } - - my $targetPath - = "$self->{'build-path'}/lib/modules/$self->{'kernel-version'}"; - $self->addCMD("mkdir -p $targetPath"); - $self->addCMD("cp -p $sourcePath/modules.* $targetPath/"); - - # add a couple of kernel modules that we expect to be used in stage3 - # (some of these modules do not exist on all distros, so they will be - # filtered out again by the respective distro object): - my @kernelModules = qw( - af_packet unix hid usbhid uhci-hcd ohci-hcd - ); - push @kernelModules, @{ $self->{'suggested-kernel-modules'} }; - - push @kernelModules, split ' ', $self->{attrs}->{ramfs_fsmods}; - push @kernelModules, split ' ', $self->{attrs}->{ramfs_miscmods}; - push @kernelModules, split ' ', $self->{attrs}->{ramfs_nicmods}; - - # a function that determines dependent modules recursively - my $addDependentsSub; - $addDependentsSub = sub { - my $modulePath = shift; - foreach my $dependentModule (@{$dependentModules{$modulePath}}) { - next if $modulesToBeCopied{$dependentModule}; - $modulesToBeCopied{$dependentModule} = 1; - $addDependentsSub->($dependentModule); - } - }; - - # start with the given kernel modules (names) and build a list of all - # required modules - foreach my $kernelModule (@kernelModules) { - if (!$modulePath{$kernelModule}) { - if (! grep { $_ eq $kernelModule } - @{ $self->{'filtered-kernel-modules'} } - ) { - warn _tr( - 'kernel module "%s" not found (in modules.dep)', - $kernelModule - ); - } - } - foreach my $modulePath (@{$modulePath{$kernelModule}}) { - next if $modulesToBeCopied{$modulePath}; - $modulesToBeCopied{$modulePath} = 1; - $addDependentsSub->($modulePath); - } - } - - # copy all the modules that we think are required - foreach my $moduleToBeCopied (sort keys %modulesToBeCopied) { - my $targetDir = "$self->{'build-path'}" . dirname($moduleToBeCopied); - $self->addCMD("mkdir -p $targetDir"); - my $source = followLink( - "$self->{'root-path'}$moduleToBeCopied", $self->{'root-path'} - ); - my $target = "$self->{'build-path'}$moduleToBeCopied"; - $self->addCMD("cp -p --dereference $source $target"); - } - - return; -} - -sub _copyPreAndPostinitFiles -{ - my $self = shift; - - foreach my $cfg ( - 'default/initramfs/preinit.local', - "$self->{'system-name'}/initramfs/preinit.local", - 'default/initramfs/postinit.local', - "$self->{'system-name'}/initramfs/postinit.local" - ) { - my $cfgPath = "$openslxConfig{'private-path'}/config/$cfg"; - next if !-f $cfgPath; - $self->addCMD("cp -p $cfgPath $self->{'build-path'}/bin/"); - } - return; -} - -sub _platformSpecificFileFor -{ - my $self = shift; - my $binary = shift; - - if ($self->{'system-name'} =~ m{64}) { - return $binary . '.x86_64'; - } - return $binary . '.i586'; -} - -sub _addRequiredFSMods -{ - my $self = shift; - - my $osExportEngine = instantiateClass("OpenSLX::OSExport::Engine"); - $osExportEngine->initializeFromExisting($self->{'export-name'}); - my $fsMods = $self->{attrs}->{ramfs_fsmods} || ''; - foreach my $fsMod ($osExportEngine->requiredFSMods()) { - $fsMods .= " $fsMod" if $fsMods !~ m{$fsMod}; - } - $self->{attrs}->{ramfs_fsmods} = $fsMods; - - return; -} - -sub _writeInitramfsSetup -{ - my $self = shift; - - # generate initramfs-setup file containing attributes that are - # relevant for the initramfs only (before there's a root-FS): - my $initramfsAttrs = { - 'host_name' => 'slx-client', # just to have something at all - 'ramfs_fsmods' => $self->{attrs}->{ramfs_fsmods} || '', - 'ramfs_miscmods' => $self->{attrs}->{ramfs_miscmods} || '', - 'ramfs_nicmods' => $self->{attrs}->{ramfs_nicmods} || '', - 'rootfs' => $self->{'export-uri'} || '', - }; - my $content = "# attributes set by slxconfig-demuxer:\n"; - foreach my $attr (keys %$initramfsAttrs) { - $content .= qq[$attr="$initramfsAttrs->{$attr}"\n]; - } - $self->addCMD( { - file => "$self->{'build-path'}/etc/initramfs-setup", - content => $content - } ); - - return; -} - -sub _writeSlxSystemConf -{ - my $self = shift; - - # generate slxsystem.conf file with variables that are needed - # in stage3 init. - # TODO: either put this stuff into initramfs-setup or find another solution - my $date = strftime("%d.%m.%Y", localtime); - my $slxConf = unshiftHereDoc(<<" End-of-Here"); - slxconf_date=$date - slxconf_kernver=$self->{'kernel-version'} - slxconf_listnwmod="$self->{attrs}->{ramfs_nicmods}" - slxconf_distro_name=$self->{'distro-name'} - slxconf_distro_ver=$self->{'distro-ver'} - slxconf_system_name=$self->{'system-name'} - slxconf_slxver="$self->{'slx-version'}" - End-of-Here - $self->addCMD( { - file => "$self->{'build-path'}/etc/slxsystem.conf", - content => $slxConf - } ); - - return; -} - -sub _calloutToPlugins -{ - my $self = shift; - - my $pluginInitdPath = "$self->{'build-path'}/etc/plugin-init.d"; - my $initHooksPath = "$self->{'build-path'}/etc/init-hooks"; - $self->addCMD("mkdir -p $pluginInitdPath $initHooksPath"); - - foreach my $pluginName (@{$self->{'plugins'}}) { - my $plugin = OpenSLX::OSPlugin::Roster->getPlugin($pluginName); - next if !$plugin; - - # create a hash only containing the attributes relating to the - # current plugin - my $allAttrs = $self->{attrs}; - my %pluginAttrs; - for my $attrName (grep { $_ =~ m{^${pluginName}::} } keys %$allAttrs) { - $pluginAttrs{$attrName} = $allAttrs->{$attrName}; - } - - # let plugin setup itself in the initramfs - $plugin->setupPluginInInitramfs(\%pluginAttrs, $self); - } - return; -} - -sub _createInitRamFS -{ - my $self = shift; - - my $buildPath = $self->{'build-path'}; - $self->addCMD( - "cd $buildPath " - . "&& find . " - . "| cpio -H newc --quiet --create " - . "| gzip -9 >$self->{initramfs}" - ); - - return; -} - -1; -################################################################################ - -=pod - -=head1 NAME - -OpenSLX::MakeInitRamFS::Engine - -=head1 SYNOPSIS - -=head1 DESCRIPTION - -... - -=cut diff --git a/lib/OpenSLX/LibScanner.pm b/lib/OpenSLX/LibScanner.pm new file mode 100644 index 00000000..e1f42ba4 --- /dev/null +++ b/lib/OpenSLX/LibScanner.pm @@ -0,0 +1,262 @@ +# Copyright (c) 2006-2008 - OpenSLX GmbH +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# LibScanner.pm +# - module that recursively scans a given binary for library dependencies +# ----------------------------------------------------------------------------- +package OpenSLX::LibScanner; + +use strict; +use warnings; + +use File::Find; +use File::Path; + +use OpenSLX::Basics; +use OpenSLX::Utils; + +################################################################################ +### interface methods +################################################################################ +sub new +{ + my $class = shift; + my $params = shift || {}; + + checkParams($params, { + 'root-path' => '!', + 'verbose' => '?', + } ); + + my $self = { + rootPath => $params->{'root-path'}, + verbose => $params->{'verbose'} || 0, + }; + + return bless $self, $class; +} + +sub determineRequiredLibs +{ + my $self = shift; + my @binaries = @_; + + $self->{filesToDo} = []; + $self->{libs} = []; + $self->{libInfo} = {}; + + $self->_fetchLoaderConfig(); + + foreach my $binary (@binaries) { + if (substr($binary, 0, 1) ne '/') { + # force relative paths relative to $rootPath: + $binary = "$self->{rootPath}/$binary"; + } + if (!-e $binary) { + warn _tr("$0: unable to find file '%s', skipping it\n", $binary); + next; + } + push @{$self->{filesToDo}}, $binary; + } + + foreach my $file (@{$self->{filesToDo}}) { + $self->_addLibsForBinary($file); + } + + return @{$self->{libs}}; +} + +sub _fetchLoaderConfig +{ + my $self = shift; + + my @libFolders; + + if (!-e "$self->{rootPath}/etc") { + die _tr("'%s'-folder not found, maybe wrong root-path?\n", + "$self->{rootPath}/etc"); + } + $self->_fetchLoaderConfigFile("$self->{rootPath}/etc/ld.so.conf"); + + # add "trusted" folders /lib and /usr/lib if not already in place: + if (!grep { m[^$self->{rootPath}/lib$] } @libFolders) { + push @libFolders, "$self->{rootPath}/lib"; + } + if (!grep { m[^$self->{rootPath}/usr/lib$] } @libFolders) { + push @libFolders, "$self->{rootPath}/usr/lib"; + } + + # add lib32-folders for 64-bit Debians, as they do not + # refer those in ld.so.conf (which I find strange...) + if (-e '/lib32' && !grep { m[^$self->{rootPath}/lib32$] } @libFolders) { + push @libFolders, "$self->{rootPath}/lib32"; + } + if (-e '/usr/lib32' + && !grep { m[^$self->{rootPath}/usr/lib32$] } @libFolders) + { + push @libFolders, "$self->{rootPath}/usr/lib32"; + } + + push @{$self->{libFolders}}, @libFolders; + + return; +} + +sub _fetchLoaderConfigFile +{ + my $self = shift; + my $ldConfFile = shift; + + return unless -e $ldConfFile; + my $ldconfFH; + if (!open($ldconfFH, '<', $ldConfFile)) { + warn(_tr("unable to open file '%s' (%s)", $ldConfFile, $!)); + return; + } + while (<$ldconfFH>) { + chomp; + if (m{^\s*include\s+(.+?)\s*$}i) { + my @incFiles = glob("$self->{rootPath}$1"); + foreach my $incFile (@incFiles) { + if ($incFile) { + $self->_fetchLoaderConfigFile($incFile); + } + } + next; + } + if (m{\S+}i) { + s[=.+][]; + # remove any lib-type specifications (e.g. '=libc5') + push @{$self->{libFolders}}, "$self->{rootPath}$_"; + } + } + close $ldconfFH + or die(_tr("unable to close file '%s' (%s)", $ldConfFile, $!)); + return; +} + +sub _addLibsForBinary +{ + my $self = shift; + my $binary = shift; + + # first do some checks: + warn _tr("analyzing '%s'...\n", $binary) if $self->{verbose}; + my $fileInfo = `file --dereference --brief --mime $binary 2>/dev/null`; + if ($?) { + die _tr("unable to fetch file info for '%s', giving up!\n", $binary); + } + chomp $fileInfo; + warn _tr("\tinfo is: '%s'...\n", $fileInfo) if $self->{verbose}; + if ($fileInfo !~ m[^application/(x-executable|x-shared)]i) { + # ignore anything that's not an executable or a shared library + warn _tr( + "%s: ignored, as it isn't an executable or a shared library\n", + $binary + ); + next; + } + + # fetch file info again, this time without '--mime' in order to get the architecture + # bitwidth: + $fileInfo = `file --dereference --brief $binary 2>/dev/null`; + if ($?) { + die _tr("unable to fetch file info for '%s', giving up!\n", $binary); + } + chomp $fileInfo; + warn _tr("\tinfo is: '%s'...\n", $fileInfo) if $self->{verbose}; + my $bitwidth = ($fileInfo =~ m[64-bit]i) ? 64 : 32; + # determine whether binary is 32- or 64-bit platform + + # now find out about needed libs, we first try objdump... + warn _tr("\ttrying objdump...\n") if $self->{verbose}; + my $res = `objdump -p $binary 2>/dev/null`; + if (!$?) { + # find out if rpath is set for binary: + my $rpath; + if ($res =~ m[^\s*RPATH\s*(\S+)]im) { + $rpath = $1; + warn _tr("\trpath='%s'\n", $rpath) if $self->{verbose}; + } + while ($res =~ m[^\s*NEEDED\s*(.+?)\s*$]gm) { + $self->_addLib($1, $bitwidth, $rpath); + } + } else { + # ...objdump failed, so we try readelf instead: + warn _tr("\ttrying readelf...\n") if $self->{verbose}; + $res = `readelf -d $binary 2>/dev/null`; + if ($?) { + die _tr( + "neither objdump nor readelf seems to be installed, giving up!\n" + ); + } + # find out if rpath is set for binary: + my $rpath; + if ($res =~ m{Library\s*rpath:\s*\[([^\]]+)}im) { + $rpath = $1; + warn _tr("\trpath='%s'\n", $rpath) if $self->{verbose}; + } + while ($res =~ m{\(NEEDED\)[^\[]+\[(.+?)\]\s*$}gm) { + $self->_addLib($1, $bitwidth, $rpath); + } + } + return; +} + +sub _addLib +{ + my $self = shift; + my $lib = shift; + my $bitwidth = shift; + my $rpath = shift; + + if (!exists $self->{libInfo}->{$lib}) { + my $libPath; + my @folders = @{$self->{libFolders}}; + if (defined $rpath) { + # add rpath if given (explicit paths set during link stage) + push @folders, split ':', $rpath; + } + foreach my $folder (@folders) { + if (-e "$folder/$lib") { + # have library matching name, now check if the platform is ok, too: + my $libFileInfo = + `file --dereference --brief $folder/$lib 2>/dev/null`; + if ($?) { + die _tr("unable to fetch file info for '%s', giving up!\n", + $folder / $lib); + } + my $libBitwidth = ($libFileInfo =~ m[64-bit]i) ? 64 : 32; + if ($bitwidth != $libBitwidth) { + vlog( + 0, + _tr( + '%s has wrong bitwidth (%s instead of %s)', + "$folder/$lib", $libBitwidth, $bitwidth + ) + ) if $self->{verbose}; + next; + } + $libPath = "$folder/$lib"; + last; + } + } + if (!defined $libPath) { + die _tr("unable to find lib %s!\n", $lib); + } + print "found $libPath\n" if $self->{verbose}; + push @{$self->{libs}}, $libPath; + $self->{libInfo}->{$lib} = 1; + push @{$self->{filesToDo}}, $libPath; + } + return; +} + +1; -- cgit v1.2.3-55-g7522