summaryrefslogtreecommitdiff
blob: 50fc877b50ca024192d97dd23fe4f878d6fd013b (plain)
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
--- busybox-1.23.1/modutils/modprobe-small.c
+++ busybox-1.23.1-modprobe-small/modutils/modprobe-small.c
@@ -552,9 +552,23 @@ static int already_loaded(const char *na
 	return ret;
 }
 #else
-#define already_loaded(name) is_rmmod
+#define already_loaded(name) 0
 #endif
 
+static int rmmod(const char *filename)
+{
+	int r;
+	char modname[MODULE_NAME_LEN];
+
+	filename2modname(filename, modname);
+	r = delete_module(modname, O_NONBLOCK | O_EXCL);
+	dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
+	if (r != 0 && !(option_mask32 & OPT_q)) {
+		bb_perror_msg("remove '%s'", modname);
+	}
+	return r;
+}
+
 /*
  * Given modules definition and module name (or alias, or symbol)
  * load/remove the module respecting dependencies.
@@ -571,26 +585,36 @@ static void process_module(char *name, c
 	module_info **infovec;
 	module_info *info;
 	int infoidx;
-	int is_rmmod = (option_mask32 & OPT_r) != 0;
+	int is_remove = (option_mask32 & OPT_r) != 0;
 
 	dbg1_error_msg("process_module('%s','%s')", name, cmdline_options);
 
 	replace(name, '-', '_');
 
-	dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod);
+	dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove);
+
+	if (applet_name[0] == 'r') {
+		/* rmmod.
+		 * Does not remove dependencies, no need to scan, just remove.
+		 * (compat note: this allows and strips .ko suffix)
+		 */
+		rmmod(name);
+		return;
+	}
+
 	/*
-	 * We used to have "is_rmmod != already_loaded(name)" check here, but
+	 * We used to have "is_remove != already_loaded(name)" check here, but
 	 *  modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80
 	 * won't unload modules (there are more than one)
 	 * which have this alias.
 	 */
-	if (!is_rmmod && already_loaded(name)) {
+	if (!is_remove && already_loaded(name)) {
 		dbg1_error_msg("nothing to do for '%s'", name);
 		return;
 	}
 
 	options = NULL;
-	if (!is_rmmod) {
+	if (!is_remove) {
 		char *opt_filename = xasprintf("/etc/modules/%s", name);
 		options = xmalloc_open_read_close(opt_filename, NULL);
 		if (options)
@@ -624,7 +648,7 @@ static void process_module(char *name, c
 			0 /* depth */
 		);
 		dbg1_error_msg("dirscan complete");
-		/* Module was not found, or load failed, or is_rmmod */
+		/* Module was not found, or load failed, or is_remove */
 		if (module_found_idx >= 0) { /* module was found */
 			infovec = xzalloc(2 * sizeof(infovec[0]));
 			infovec[0] = &modinfo[module_found_idx];
@@ -637,7 +661,7 @@ static void process_module(char *name, c
 
 	if (!infovec) {
 		/* both dirscan and find_alias found nothing */
-		if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
+		if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
 			bb_error_msg("module '%s' not found", name);
 //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
 		goto ret;
@@ -651,29 +675,15 @@ static void process_module(char *name, c
 	 * a *list* of modinfo pointers from find_alias().
 	 */
 
-	/* rmmod or modprobe -r? unload module(s) */
-	if (is_rmmod) {
+	/* modprobe -r? unload module(s) */
+	if (is_remove) {
 		infoidx = 0;
 		while ((info = infovec[infoidx++]) != NULL) {
-			int r;
-			char modname[MODULE_NAME_LEN];
-
-			filename2modname(
-				bb_get_last_path_component_nostrip(info->pathname), modname);
-			r = delete_module(modname, O_NONBLOCK | O_EXCL);
-			dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r);
+			int r = rmmod(bb_get_last_path_component_nostrip(info->pathname));
 			if (r != 0) {
-				if (!(option_mask32 & OPT_q))
-					bb_perror_msg("remove '%s'", modname);
-				goto ret;
+				goto ret; /* error */
 			}
 		}
-
-		if (applet_name[0] == 'r') {
-			/* rmmod: do not remove dependencies, exit */
-			goto ret;
-		}
-
 		/* modprobe -r: we do not stop here -
 		 * continue to unload modules on which the module depends:
 		 * "-r --remove: option causes modprobe to remove a module.
@@ -694,7 +704,7 @@ static void process_module(char *name, c
 		}
 		free(deps);
 
-		if (is_rmmod)
+		if (is_remove)
 			continue;
 
 		/* We are modprobe: load it */
@@ -897,10 +907,10 @@ int modprobe_main(int argc UNUSED_PARAM,
 	}
 
 #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
-	/* If not rmmod, parse possible module options given on command line.
+	/* If not rmmod/-r, parse possible module options given on command line.
 	 * insmod/modprobe takes one module name, the rest are parameters. */
 	options = NULL;
-	if ('r' != applet0) {
+	if (!(option_mask32 & OPT_r)) {
 		char **arg = argv;
 		while (*++arg) {
 			/* Enclose options in quotes */
@@ -911,7 +921,7 @@ int modprobe_main(int argc UNUSED_PARAM,
 		}
 	}
 #else
-	if ('r' != applet0)
+	if (!(option_mask32 & OPT_r))
 		argv[1] = NULL;
 #endif
 
@@ -935,10 +945,11 @@ int modprobe_main(int argc UNUSED_PARAM,
 	}
 
 	/* Try to load modprobe.dep.bb */
-	load_dep_bb();
+	if ('r' != applet0) /* not rmmod */
+		load_dep_bb();
 
 	/* Load/remove modules.
-	 * Only rmmod loops here, modprobe has only argv[0] */
+	 * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */
 	do {
 		process_module(*argv, options);
 	} while (*++argv);