File: ModProbe.pm

package info (click to toggle)
yaird 0.0.12-18etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 1,432 kB
  • ctags: 725
  • sloc: perl: 4,161; xml: 3,233; ansic: 3,105; sh: 876; makefile: 150
file content (171 lines) | stat: -rw-r--r-- 5,697 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#!perl -w
#
# ModProbe -- insert modules plus dependencies
#   Copyright (C) 2005  Erik van Konijnenburg
#
#   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 St, Fifth Floor, Boston, MA  02110-1301 USA
#
# This uses modprobe to determine which files to load to get a certain
# module.  It adds two extra features:
#  - do not load blacklisted modules
#  - if we know a module is compiled into the kernel,
#    don't attempt to load it, and don't complain.
#
# Notes on the behaviour of modprobe:
#
#   modprobe --verbose --dry-run --show-depends --set-version 2.6.11 aes
#
# shows the files that are needed, regardless of whether they are
# already loaded.  Lines start with 'insmod ' for files to be loaded,
# or 'install ' for commands to be executed.
#
# Modprobe file format:
#  - characters are bytes, no messing with utf-8.
#  - backslash at end of line merges lines
#  - other \x get replaced by x
#  - ^\s*# lines are ignored
#  - lines without : are ignored.
# This means "aap: noot.#7" is a valid dependency.
# The backslash interpretation is mostly for modprobe.conf;
# depmod does not generate it.
#
# Modprobe determines module name by dropping everything after dot:
# "/lib/noot.#7" is module "noot".  We'll adopt the same policy.
#
# Depmod only grabs modules ending in .ko or .ko.gz.
#
# Note that modprobe does not discriminate against modules outside
# /lib/modules: if it's listed in modules.dep, it's a valid module.
#
# Note that redhat has a convention that modules in .../update take
# precedence over other modules with the same name.  Depmod implements
# this by not putting modules that are overridden in modules.dep.
# Thus modprobe needs no special action to support that convention.
#
# The logic modprobe uses to determine which modules to load:
# - replace hyphens with underscore
# - read config specified on command line,
#   OR modprobe.conf OR modprobe.d, only first one found.
#   Remember all "install" and "option" directives,
#   rewrite module name if an alias matches
# - if no alias found and the name is of the form 'symbol:xxx':
# 	look in modules.symbols to resolve to a module name
# - if alias found:
#	make a list of modules to load, based on modules.dep
# - else:
#	make a list of modules to load, based on modules.dep
#	if that turned up no modules AND there was no install cmd:
#		- look in modules.aliases to resolve to modulename
#		- make a list of modules to load, based on modules.dep
# - if the list to load is empty AND there was no install command:
# 	- complain.
# # in insmod():
# - recurse over the module list, most basic stuff first, doing:
# 	- if there is a command for this module name:
# 		execute it
# 	- else:
#		load the module
#
# Loading of the module is done with a system call.  The option string
# is passed as third argument; splitting the option string in separate
# module options is done in the kernel.  Double quote escapes spaces,
# double quotes themselves cannot be escaped.
#
use strict;
use warnings;
use Base;
use Conf;
use ActionList;
use Blacklist;
use KConfig;
package ModProbe;


#
# addModules -- given an actionList and list of modules,
# add actions to load all modules, plus their dependencies,
# unless blacklisted or compiled in.
#
sub addModules ($$) {
	my ($actionList, $modList) = @_;
	addOptModules ($actionList, $modList, 0);
}

# addOptModules -- the same except:
# If optional, ignore modules that are not found.
sub addOptModules ($$$) {
	my ($actionList, $modList, $optional) = @_;
	for my $moduleName (@{$modList}) {
		if (Blacklist::isBlacklisted ($moduleName)) {
			next;
		}
		if (KConfig::isBuiltIn ($moduleName)) {
			next;
		}
		addOneModule ($actionList, $moduleName, $optional);
	}
}


#
# addOneModule -- for one module, that is not blacklisted or compiled in,
# add actions to load it plus all its dependencies.
# If optional, ignore modules that are not found.
#
sub addOneModule ($$$) {
	my ($actionList, $m, $optional) = @_;
	my $v = Conf::get('version');
	Base::debug ("addOneModule: modprobe $m");

	my ($rc, $lines) = Base::runCmd (
		failOk => $optional,
		cmd => ['/sbin/modprobe', '-v', '-n',
			'--show-depends', '--set-version', $v, $m]);
	if (! $rc) {
		# modprobe failed; assume it's because of not found
		return;
	}

	for my $line (@{$lines}) {
		$line =~ s/\s+$//;
		if ($line =~ /^install (.*)/) {
			# Since we're using modprobe output,
			# we cannot refer to location of the
			# offending line in config file.
			Base::fatal ("modprobe shows that module $m needs an external program; this is not supported.  The offending line is: install $1");
		}
		elsif ($line =~ /^insmod (\S+)$/) {
			$actionList->add ("insmod", $1,
				optionList => '');
		}
		elsif ($line =~ /^insmod (\S+)\s+(.*)$/) {
			my $file = $1;
			my $option = $2;
			
			# This should allow options in modprobe.conf
			# to contain both ' and " characters and spaces.
			$option =~ s![^a-zA-Z0-9,_./=-]!\\$&!g;

			$actionList->add ("insmod", $file,
				optionList => $option);
		}
		else {
			Base::fatal ("modprobe $m - unsupported output $line");
		}
	}
}

1;