1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker * kmod-rmmod - remove modules from linux kernel using libkmod.
3*cc4ad7daSAndroid Build Coastguard Worker *
4*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2011-2013 ProFUSION embedded systems
5*cc4ad7daSAndroid Build Coastguard Worker *
6*cc4ad7daSAndroid Build Coastguard Worker * This program is free software: you can redistribute it and/or modify
7*cc4ad7daSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
8*cc4ad7daSAndroid Build Coastguard Worker * the Free Software Foundation, either version 2 of the License, or
9*cc4ad7daSAndroid Build Coastguard Worker * (at your option) any later version.
10*cc4ad7daSAndroid Build Coastguard Worker *
11*cc4ad7daSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
12*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*cc4ad7daSAndroid Build Coastguard Worker * GNU General Public License for more details.
15*cc4ad7daSAndroid Build Coastguard Worker *
16*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
17*cc4ad7daSAndroid Build Coastguard Worker * along with this program. If not, see <http://www.gnu.org/licenses/>.
18*cc4ad7daSAndroid Build Coastguard Worker */
19*cc4ad7daSAndroid Build Coastguard Worker
20*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <getopt.h>
22*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
23*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
28*cc4ad7daSAndroid Build Coastguard Worker
29*cc4ad7daSAndroid Build Coastguard Worker #include <shared/macro.h>
30*cc4ad7daSAndroid Build Coastguard Worker
31*cc4ad7daSAndroid Build Coastguard Worker #include <libkmod/libkmod.h>
32*cc4ad7daSAndroid Build Coastguard Worker
33*cc4ad7daSAndroid Build Coastguard Worker #include "kmod.h"
34*cc4ad7daSAndroid Build Coastguard Worker
35*cc4ad7daSAndroid Build Coastguard Worker #define DEFAULT_VERBOSE LOG_ERR
36*cc4ad7daSAndroid Build Coastguard Worker static int verbose = DEFAULT_VERBOSE;
37*cc4ad7daSAndroid Build Coastguard Worker static int use_syslog;
38*cc4ad7daSAndroid Build Coastguard Worker
39*cc4ad7daSAndroid Build Coastguard Worker static const char cmdopts_s[] = "fsvVwh";
40*cc4ad7daSAndroid Build Coastguard Worker static const struct option cmdopts[] = {
41*cc4ad7daSAndroid Build Coastguard Worker {"force", no_argument, 0, 'f'},
42*cc4ad7daSAndroid Build Coastguard Worker {"syslog", no_argument, 0, 's'},
43*cc4ad7daSAndroid Build Coastguard Worker {"verbose", no_argument, 0, 'v'},
44*cc4ad7daSAndroid Build Coastguard Worker {"version", no_argument, 0, 'V'},
45*cc4ad7daSAndroid Build Coastguard Worker {"help", no_argument, 0, 'h'},
46*cc4ad7daSAndroid Build Coastguard Worker {NULL, 0, 0, 0}
47*cc4ad7daSAndroid Build Coastguard Worker };
48*cc4ad7daSAndroid Build Coastguard Worker
help(void)49*cc4ad7daSAndroid Build Coastguard Worker static void help(void)
50*cc4ad7daSAndroid Build Coastguard Worker {
51*cc4ad7daSAndroid Build Coastguard Worker printf("Usage:\n"
52*cc4ad7daSAndroid Build Coastguard Worker "\t%s [options] modulename ...\n"
53*cc4ad7daSAndroid Build Coastguard Worker "Options:\n"
54*cc4ad7daSAndroid Build Coastguard Worker "\t-f, --force forces a module unload and may crash your\n"
55*cc4ad7daSAndroid Build Coastguard Worker "\t machine. This requires Forced Module Removal\n"
56*cc4ad7daSAndroid Build Coastguard Worker "\t option in your kernel. DANGEROUS\n"
57*cc4ad7daSAndroid Build Coastguard Worker "\t-s, --syslog print to syslog, not stderr\n"
58*cc4ad7daSAndroid Build Coastguard Worker "\t-v, --verbose enables more messages\n"
59*cc4ad7daSAndroid Build Coastguard Worker "\t-V, --version show version\n"
60*cc4ad7daSAndroid Build Coastguard Worker "\t-h, --help show this help\n",
61*cc4ad7daSAndroid Build Coastguard Worker program_invocation_short_name);
62*cc4ad7daSAndroid Build Coastguard Worker }
63*cc4ad7daSAndroid Build Coastguard Worker
check_module_inuse(struct kmod_module * mod)64*cc4ad7daSAndroid Build Coastguard Worker static int check_module_inuse(struct kmod_module *mod) {
65*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *holders;
66*cc4ad7daSAndroid Build Coastguard Worker int state, ret;
67*cc4ad7daSAndroid Build Coastguard Worker
68*cc4ad7daSAndroid Build Coastguard Worker state = kmod_module_get_initstate(mod);
69*cc4ad7daSAndroid Build Coastguard Worker
70*cc4ad7daSAndroid Build Coastguard Worker if (state == KMOD_MODULE_BUILTIN) {
71*cc4ad7daSAndroid Build Coastguard Worker ERR("Module %s is builtin.\n", kmod_module_get_name(mod));
72*cc4ad7daSAndroid Build Coastguard Worker return -ENOENT;
73*cc4ad7daSAndroid Build Coastguard Worker } else if (state < 0) {
74*cc4ad7daSAndroid Build Coastguard Worker ERR("Module %s is not currently loaded\n",
75*cc4ad7daSAndroid Build Coastguard Worker kmod_module_get_name(mod));
76*cc4ad7daSAndroid Build Coastguard Worker return -ENOENT;
77*cc4ad7daSAndroid Build Coastguard Worker }
78*cc4ad7daSAndroid Build Coastguard Worker
79*cc4ad7daSAndroid Build Coastguard Worker holders = kmod_module_get_holders(mod);
80*cc4ad7daSAndroid Build Coastguard Worker if (holders != NULL) {
81*cc4ad7daSAndroid Build Coastguard Worker struct kmod_list *itr;
82*cc4ad7daSAndroid Build Coastguard Worker
83*cc4ad7daSAndroid Build Coastguard Worker ERR("Module %s is in use by:", kmod_module_get_name(mod));
84*cc4ad7daSAndroid Build Coastguard Worker
85*cc4ad7daSAndroid Build Coastguard Worker kmod_list_foreach(itr, holders) {
86*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *hm = kmod_module_get_module(itr);
87*cc4ad7daSAndroid Build Coastguard Worker fprintf(stderr, " %s", kmod_module_get_name(hm));
88*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(hm);
89*cc4ad7daSAndroid Build Coastguard Worker }
90*cc4ad7daSAndroid Build Coastguard Worker fputc('\n', stderr);
91*cc4ad7daSAndroid Build Coastguard Worker
92*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref_list(holders);
93*cc4ad7daSAndroid Build Coastguard Worker return -EBUSY;
94*cc4ad7daSAndroid Build Coastguard Worker }
95*cc4ad7daSAndroid Build Coastguard Worker
96*cc4ad7daSAndroid Build Coastguard Worker ret = kmod_module_get_refcnt(mod);
97*cc4ad7daSAndroid Build Coastguard Worker if (ret > 0) {
98*cc4ad7daSAndroid Build Coastguard Worker ERR("Module %s is in use\n", kmod_module_get_name(mod));
99*cc4ad7daSAndroid Build Coastguard Worker return -EBUSY;
100*cc4ad7daSAndroid Build Coastguard Worker } else if (ret == -ENOENT) {
101*cc4ad7daSAndroid Build Coastguard Worker ERR("Module unloading is not supported\n");
102*cc4ad7daSAndroid Build Coastguard Worker }
103*cc4ad7daSAndroid Build Coastguard Worker
104*cc4ad7daSAndroid Build Coastguard Worker return ret;
105*cc4ad7daSAndroid Build Coastguard Worker }
106*cc4ad7daSAndroid Build Coastguard Worker
do_rmmod(int argc,char * argv[])107*cc4ad7daSAndroid Build Coastguard Worker static int do_rmmod(int argc, char *argv[])
108*cc4ad7daSAndroid Build Coastguard Worker {
109*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx *ctx;
110*cc4ad7daSAndroid Build Coastguard Worker const char *null_config = NULL;
111*cc4ad7daSAndroid Build Coastguard Worker int flags = 0;
112*cc4ad7daSAndroid Build Coastguard Worker int i, err, r = 0;
113*cc4ad7daSAndroid Build Coastguard Worker
114*cc4ad7daSAndroid Build Coastguard Worker for (;;) {
115*cc4ad7daSAndroid Build Coastguard Worker int c, idx = 0;
116*cc4ad7daSAndroid Build Coastguard Worker c = getopt_long(argc, argv, cmdopts_s, cmdopts, &idx);
117*cc4ad7daSAndroid Build Coastguard Worker if (c == -1)
118*cc4ad7daSAndroid Build Coastguard Worker break;
119*cc4ad7daSAndroid Build Coastguard Worker switch (c) {
120*cc4ad7daSAndroid Build Coastguard Worker case 'f':
121*cc4ad7daSAndroid Build Coastguard Worker flags |= KMOD_REMOVE_FORCE;
122*cc4ad7daSAndroid Build Coastguard Worker break;
123*cc4ad7daSAndroid Build Coastguard Worker case 's':
124*cc4ad7daSAndroid Build Coastguard Worker use_syslog = 1;
125*cc4ad7daSAndroid Build Coastguard Worker break;
126*cc4ad7daSAndroid Build Coastguard Worker case 'v':
127*cc4ad7daSAndroid Build Coastguard Worker verbose++;
128*cc4ad7daSAndroid Build Coastguard Worker break;
129*cc4ad7daSAndroid Build Coastguard Worker case 'h':
130*cc4ad7daSAndroid Build Coastguard Worker help();
131*cc4ad7daSAndroid Build Coastguard Worker return EXIT_SUCCESS;
132*cc4ad7daSAndroid Build Coastguard Worker case 'V':
133*cc4ad7daSAndroid Build Coastguard Worker puts(PACKAGE " version " VERSION);
134*cc4ad7daSAndroid Build Coastguard Worker puts(KMOD_FEATURES);
135*cc4ad7daSAndroid Build Coastguard Worker return EXIT_SUCCESS;
136*cc4ad7daSAndroid Build Coastguard Worker case '?':
137*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
138*cc4ad7daSAndroid Build Coastguard Worker default:
139*cc4ad7daSAndroid Build Coastguard Worker ERR("unexpected getopt_long() value '%c'.\n", c);
140*cc4ad7daSAndroid Build Coastguard Worker return EXIT_FAILURE;
141*cc4ad7daSAndroid Build Coastguard Worker }
142*cc4ad7daSAndroid Build Coastguard Worker }
143*cc4ad7daSAndroid Build Coastguard Worker
144*cc4ad7daSAndroid Build Coastguard Worker log_open(use_syslog);
145*cc4ad7daSAndroid Build Coastguard Worker
146*cc4ad7daSAndroid Build Coastguard Worker if (optind >= argc) {
147*cc4ad7daSAndroid Build Coastguard Worker ERR("missing module name.\n");
148*cc4ad7daSAndroid Build Coastguard Worker r = EXIT_FAILURE;
149*cc4ad7daSAndroid Build Coastguard Worker goto done;
150*cc4ad7daSAndroid Build Coastguard Worker }
151*cc4ad7daSAndroid Build Coastguard Worker
152*cc4ad7daSAndroid Build Coastguard Worker ctx = kmod_new(NULL, &null_config);
153*cc4ad7daSAndroid Build Coastguard Worker if (!ctx) {
154*cc4ad7daSAndroid Build Coastguard Worker ERR("kmod_new() failed!\n");
155*cc4ad7daSAndroid Build Coastguard Worker r = EXIT_FAILURE;
156*cc4ad7daSAndroid Build Coastguard Worker goto done;
157*cc4ad7daSAndroid Build Coastguard Worker }
158*cc4ad7daSAndroid Build Coastguard Worker
159*cc4ad7daSAndroid Build Coastguard Worker log_setup_kmod_log(ctx, verbose);
160*cc4ad7daSAndroid Build Coastguard Worker
161*cc4ad7daSAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
162*cc4ad7daSAndroid Build Coastguard Worker struct kmod_module *mod;
163*cc4ad7daSAndroid Build Coastguard Worker const char *arg = argv[i];
164*cc4ad7daSAndroid Build Coastguard Worker struct stat st;
165*cc4ad7daSAndroid Build Coastguard Worker if (stat(arg, &st) == 0)
166*cc4ad7daSAndroid Build Coastguard Worker err = kmod_module_new_from_path(ctx, arg, &mod);
167*cc4ad7daSAndroid Build Coastguard Worker else
168*cc4ad7daSAndroid Build Coastguard Worker err = kmod_module_new_from_name(ctx, arg, &mod);
169*cc4ad7daSAndroid Build Coastguard Worker
170*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
171*cc4ad7daSAndroid Build Coastguard Worker ERR("could not use module %s: %s\n", arg,
172*cc4ad7daSAndroid Build Coastguard Worker strerror(-err));
173*cc4ad7daSAndroid Build Coastguard Worker break;
174*cc4ad7daSAndroid Build Coastguard Worker }
175*cc4ad7daSAndroid Build Coastguard Worker
176*cc4ad7daSAndroid Build Coastguard Worker if (!(flags & KMOD_REMOVE_FORCE) && check_module_inuse(mod) < 0) {
177*cc4ad7daSAndroid Build Coastguard Worker r++;
178*cc4ad7daSAndroid Build Coastguard Worker goto next;
179*cc4ad7daSAndroid Build Coastguard Worker }
180*cc4ad7daSAndroid Build Coastguard Worker
181*cc4ad7daSAndroid Build Coastguard Worker err = kmod_module_remove_module(mod, flags);
182*cc4ad7daSAndroid Build Coastguard Worker if (err < 0) {
183*cc4ad7daSAndroid Build Coastguard Worker ERR("could not remove module %s: %s\n", arg,
184*cc4ad7daSAndroid Build Coastguard Worker strerror(-err));
185*cc4ad7daSAndroid Build Coastguard Worker r++;
186*cc4ad7daSAndroid Build Coastguard Worker }
187*cc4ad7daSAndroid Build Coastguard Worker next:
188*cc4ad7daSAndroid Build Coastguard Worker kmod_module_unref(mod);
189*cc4ad7daSAndroid Build Coastguard Worker }
190*cc4ad7daSAndroid Build Coastguard Worker
191*cc4ad7daSAndroid Build Coastguard Worker kmod_unref(ctx);
192*cc4ad7daSAndroid Build Coastguard Worker
193*cc4ad7daSAndroid Build Coastguard Worker done:
194*cc4ad7daSAndroid Build Coastguard Worker log_close();
195*cc4ad7daSAndroid Build Coastguard Worker
196*cc4ad7daSAndroid Build Coastguard Worker return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
197*cc4ad7daSAndroid Build Coastguard Worker }
198*cc4ad7daSAndroid Build Coastguard Worker
199*cc4ad7daSAndroid Build Coastguard Worker const struct kmod_cmd kmod_cmd_compat_rmmod = {
200*cc4ad7daSAndroid Build Coastguard Worker .name = "rmmod",
201*cc4ad7daSAndroid Build Coastguard Worker .cmd = do_rmmod,
202*cc4ad7daSAndroid Build Coastguard Worker .help = "compat rmmod command",
203*cc4ad7daSAndroid Build Coastguard Worker };
204