summaryrefslogtreecommitdiffstats
path: root/perl-install/modules/modprobe_conf.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/modules/modprobe_conf.pm')
-rw-r--r--perl-install/modules/modprobe_conf.pm164
1 files changed, 164 insertions, 0 deletions
diff --git a/perl-install/modules/modprobe_conf.pm b/perl-install/modules/modprobe_conf.pm
new file mode 100644
index 000000000..7989096f8
--- /dev/null
+++ b/perl-install/modules/modprobe_conf.pm
@@ -0,0 +1,164 @@
+package modules::modprobe_conf;
+
+use log;
+use common;
+# perl_checker: require modules::any_conf
+
+our @ISA = qw(modules::any_conf);
+
+
+sub file { '/etc/modprobe.conf' }
+sub handled_fields { qw(alias options install remove) }
+
+sub mapping {
+ my ($_conf, @modules) = @_;
+ my @l = map { modules::mapping_24_26($_) } @modules;
+ wantarray() ? @l : $l[0];
+}
+
+sub get_above {
+ my ($conf, $module) = @_;
+ $module = $conf->mapping($module);
+
+ my (undef, $after) = parse_non_virtual($module, $conf->{$module}{install}) or return;
+ my ($l, $_other_cmds) = partition_modprobes($after);
+ @$l;
+}
+sub set_above {
+ my ($conf, $module, $o_modules) = @_;
+ $module = $conf->mapping($module);
+ my @modules = $conf->mapping(split(' ', $o_modules || ''));
+
+ { #- first add to "install" command
+ my ($before, $after) = parse_non_virtual($module, $conf->{$module}{install});
+ my ($_previous_modules, $other_cmds) = partition_modprobes($after || '');
+ $after = join('; ', @$other_cmds, map { "/sbin/modprobe $_" } @modules);
+ $conf->{$module}{install} = unparse_non_virtual($module, '--ignore-install', $before, $after);
+ }
+ { #- then to "remove" command
+ my ($before, $after) = parse_non_virtual($module, $conf->{$module}{remove});
+ my ($_previous_modules, $other_cmds) = partition_modprobes($before || '');
+ $before = join('; ', @$other_cmds, map { "/sbin/modprobe -r $_" } @modules);
+ $conf->{$module}{remove} = unparse_non_virtual($module, '-r --ignore-remove', $before, $after);
+ }
+}
+
+sub create_from_old() {
+ #- use module-init-tools script
+ run_program::rooted($::prefix, "/sbin/generate-modprobe.conf", ">", file());
+}
+
+sub read {
+ my ($type, $o_file) = @_;
+
+ my $file = $o_file || do {
+ my $f = $::prefix . file();
+ if (!-e $f && -e "$::prefix/etc/modules.conf") {
+ create_from_old();
+ }
+ $f;
+ };
+
+ my $conf = modules::any_conf::read_handled($type, $file);
+
+ extract_probeall_field($conf);
+
+ $conf;
+}
+
+sub write {
+ my ($conf, $o_file) = @_;
+
+ remove_probeall_field($conf);
+
+ my $_b = before_leaving { extract_probeall_field($conf) };
+
+ modules::any_conf::write($conf, $o_file);
+}
+
+
+
+################################################################################
+sub remove_braces {
+ my ($s) = @_;
+ $s =~ s/^\s*\{\s*(.*)\s*;\s*\}\s*$/$1/;
+ $s;
+}
+
+sub parse_non_virtual {
+ my ($module, $s) = @_;
+ my ($before, $options, $after) =
+ $s =~ m!^(?:(.*);)?
+ \s*(?:/sbin/)?modprobe\s+(-\S+\s+)*\Q$module\E
+ \s*(?:&&\s*(.*))?$!x
+ or return;
+ $options =~ /--ignore-(install|remove)\b/ or return;
+
+ ($before, $after) = map { remove_braces($_ || '') } $before, $after;
+ $after =~ s!\s*;\s*/bin/true$!!;
+
+ $before, $after;
+}
+
+sub unparse_non_virtual {
+ my ($module, $mode, $before, $after) = @_;
+ ($before ? "$before; " : '')
+ . (($before || $after) ? "/sbin/modprobe --first-time $mode $module" : '')
+ . ($after ? " && { $after; /bin/true; }" : '');
+}
+
+sub partition_modprobes {
+ my ($s) = @_;
+
+ my (@modprobes, @other_cmds);
+ my @l = split(/\s*;\s*/, $s);
+ foreach (@l) {
+ if (m!^(?:/sbin/)?modprobe\s+(?:-r\s+)?(\S+)$!) {
+ push @modprobes, $1;
+ } else {
+ push @other_cmds, $1;
+ }
+ }
+ \@modprobes, \@other_cmds;
+}
+
+sub parse_for_probeall {
+ my ($module, $s) = @_;
+
+ parse_non_virtual($module, $s) and return;
+ if ($s =~ /[{&|]/) {
+ log::l("weird install line in modprobe.conf for $module: $s");
+ return;
+ }
+ $s ne '/bin/true' or return; #- we have "alias $module off" here
+
+ $s =~ s!\s*;\s*/bin/true$!!;
+
+ my ($l, $other_cmds) = partition_modprobes($s);
+
+ @$other_cmds ? undef : $l;
+}
+
+sub extract_probeall_field {
+ my ($conf) = @_;
+
+ foreach my $module (keys %$conf) {
+ $conf->{$module}{install} or next;
+ my $l = parse_for_probeall($module, $conf->{$module}{install}) or next;
+
+ $conf->{$module}{probeall} = join(' ', @$l);
+ delete $conf->{$module}{install};
+ }
+}
+
+sub remove_probeall_field {
+ my ($conf) = @_;
+
+ foreach my $module (keys %$conf) {
+ my $modules = delete $conf->{$module}{probeall} or next;
+
+ $conf->{$module}{install} = join('; ', (map { "/sbin/modprobe $_" } split(' ', $modules)), '/bin/true');
+ }
+}
+
+1;