ACC SHELL

Path : /sbin/
File Upload :
Current File : //sbin/mkinitrd_setup

#!/usr/bin/perl
#
# Install initrd scripts
#

use strict;
use Getopt::Long;

my @scripts_boot = ();
my @scripts_setup = ();
my %level_boot = ();
my %level_setup = ();
my %depends_boot = ();
my %depends_setup = ();
my %providedby_boot = ();
my %providedby_setup = ();

my $debug = 0;
my $offset = 0;
my $installdir = "/lib/mkinitrd";
my $scriptdir = "$installdir/scripts";
my $dohelp = 0;

my %stages = (
    setup => 0,
    filesystem => 1,
    crypto => 2,
    volumemanager => 3,
    softraid => 4,
    partitions => 5,
    devicemapper => 6,
    block => 7,
    device => 8,
    boot => 9,
);

sub dprintf
{
    if ($debug > 0) {
        printf @_;
    }
}

sub resolve_dependency
{
    my $section = shift(@_);
    my $name = shift(@_);
    my $oldlevel;
    my $level;
    my $depends;
    my $providedby;

    if ( $section eq "setup" ) {
        $level = \%level_setup;
        $depends = \%depends_setup;
        $providedby= \%providedby_setup;
    } else {
        $level = \%level_boot;
        $depends = \%depends_boot;
        $providedby= \%providedby_boot;
    }
    $oldlevel = $$level{$name};

    foreach my $elem (split(' ',$$depends{$name})) {
        my $newlevel = -1;

        foreach my $n (split(' ',$$providedby{$elem})) {
            $newlevel = resolve_dependency($section, $n);
            if ( $oldlevel <= $newlevel) {
                $oldlevel = $newlevel + 1;
            }
        }

        if ($newlevel == -1) {
            dprintf "Unresolved dependency \"%s\" ", $elem;
        }
    }
    dprintf "%s/%s (%s) ", $section, $name, $oldlevel;
    $$level{$name} = $oldlevel;

    return $oldlevel;
}

sub scan_section
{
    my @scripts = @_;
    my @scrlist = ();
    my $depends;
    my $level;
    my $providedby;

    SCAN: foreach $_ (@scripts) {
        my $provides;
        my $section;
        my $scriptname;
        my $level;
        my $depends;
        my $providedby;
        my $scrlist;

        if (/(.*)-(.*)\.sh$/) {
            if (($1 ne "setup" ) && ($1 ne "boot")) {
                next SCAN;
            }
            $section = $1;
            $scriptname = $2;
        } else {
            next SCAN;
        }

        if ( $section eq "setup" ) {
            $level = \%level_setup;
            $depends = \%depends_setup;
            $providedby= \%providedby_setup;
            $scrlist = \@scripts_setup;
        } else {
            $level = \%level_boot;
            $depends = \%depends_boot;
            $providedby= \%providedby_boot;
            $scrlist = \@scripts_boot;
        }

        dprintf "scanning script %s (name %s)\n", $_, $scriptname;
        dprintf "\tsection: %s\n", $section;
        $provides = $scriptname;

        open(SCR, "$scriptdir/$_");

        while (<SCR>) {
            chomp;
            if ( /^\#%stage: (.*)/ ) {
                if (! defined $stages{$1}) {
                    dprintf "%s: Invalid stage \"%s\"\n", $scriptname, $1;
                    close(SCR);
                    next SCAN;
                }
                if ($section eq "setup") {
                    $$level{$scriptname} = ($stages{$1} * 10) + 1;
                } else {
                    $$level{$scriptname} = 91 - ($stages{$1} * 10);
                }
                dprintf "\tstage %s: %d\n", $1, $$level{$scriptname};
            }
            if ( /^\#%depends: (.*)/ ) {
                dprintf "\tdepends on %s\n", $1;
                $$depends{$scriptname} = $1;
            }
            if ( /\#%provides: (.*)/ ) {
                $provides = join(' ',$provides,$1);
            }

        }
        close SCR;

        @$scrlist = (@$scrlist,$scriptname);

        dprintf "\tprovides %s\n", $provides;
        foreach my $elem (split(' ',$provides)) {
            $$providedby{$elem} = join(' ', $$providedby{$elem},$scriptname);
        }
    }
}

sub usage {
    print <<EOF;
usage:
        mkinitrd_setup [-s|--scriptdir <scriptdir>]
                [-i|--installdir <installdir>]
                [-d|--debug] [-o|--offset <offset>] [-h|--help]

        Install mkinitrd scripts. Options are:
        -s|--scriptdir  Install initrd scripts from dir <scriptdir>
        -i|--installdir Install initrd scripts in dir <installdir>
        -d|--debug      Enable debug output
        -o|--offset     Use <offset> between script numbers.

EOF
}

Getopt::Long::Configure('no_ignore_case');

if (!GetOptions('scriptdir|s=s' => \$scriptdir,
                'installdir|i=s' => \$installdir,
                'debug|d' => \$debug,
                'offset|o' => \$offset,
                'help|h' => \$dohelp
                )) {
    usage();
    exit 1;
}
if ( ! -d $installdir ) {
    print "Installation directory $installdir does not exist!\n";
    $dohelp++;
}
if ( $dohelp == 0 && ! -d "$installdir/setup" ) {
    print "Installation directory $installdir/setup does not exist!\n";
    $dohelp++;
}
if ( $dohelp == 0 && ! -d "$installdir/boot" ) {
    print "Installation directory $installdir/boot does not exist!\n";
    $dohelp++;
}
if ( $dohelp == 0 && ! -d $scriptdir ) {
    print "Script directory $scriptdir does not exist!\n";
    $dohelp++;
}
if ($dohelp > 0) {
    usage();
    exit 0;
}

print "Scanning scripts ...\n";
opendir(DIR, $scriptdir);
my @scripts = grep { /.*\.sh$/ && -f "$scriptdir/$_" } readdir(DIR);
closedir DIR;

# Scan scripts
scan_section(@scripts);

print "Resolve dependencies ...\n";
# Resolve dependencies
foreach my $scr (@scripts_setup) {
    resolve_dependency("setup", $scr);
    dprintf "\n";
}

foreach my $scr (@scripts_boot) {
    resolve_dependency("boot", $scr);
    dprintf "\n";
}

print "Install symlinks in $installdir/setup ...\n";
chdir "$installdir/setup" || die "Can't chdir to $installdir/setup : $!";

opendir(DIR, ".");
my @links = grep { -l "$_" } readdir(DIR);
closedir DIR;

foreach $_ (@links) {
    unlink || printf "Can't unlink %s: %s\n", $_, $!;
}

foreach (@scripts_setup) {
    my $level = \%level_setup;
    my $lvl = $$level{$_};
    my $linkname;
    my $target;
    my $ret;

    $linkname = sprintf "%02d-%s.sh", $lvl, $_;
    $target = sprintf "../scripts/setup-%s.sh", $_;
    # Strictly speaking not required, but ...
    next if -l $linkname;
    dprintf "Linking %s to %s\n", $target, $linkname;
    $ret = symlink($target, $linkname);
    if ( $ret < 1 ) {
        printf "Failed to create symlink %s: %s\n", $linkname, $!;
    }
}

print "Install symlinks in $installdir/boot ...\n";
chdir "../boot" || die "Can't chdir to $installdir/boot: $!";

opendir(DIR, ".");
@links = grep { -l "$_" } readdir(DIR);
closedir DIR;

foreach $_ (@links) {
    unlink || printf "Can't unlink %s: %s\n", $_, $!;
}

foreach (@scripts_boot) {
    my $level = \%level_boot;
    my $lvl = $$level{$_};
    my $linkname;
    my $target;
    my $ret;

    $linkname = sprintf "%02d-%s.sh", $lvl, $_;
    $target = sprintf "../scripts/boot-%s.sh", $_;
    # Strictly speaking not required, but ...
    next if -l $linkname;
    dprintf "Linking %s to %s\n", $target, $linkname;
    $ret = symlink($target, $linkname);
    if ( $ret < 1 ) {
        printf "Failed to create symlink %s: %s\n", $linkname, $!;
    }
}


ACC SHELL 2018