1 /* vi: set sw=4 ts=4: */
2 /*
3 * Mini rmmod implementation for busybox
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 * Copyright (C) 2008 Timo Teras <timo.teras@iki.fi>
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10 //config:config RMMOD
11 //config: bool "rmmod (3.3 kb)"
12 //config: default y
13 //config: help
14 //config: rmmod is used to unload specified modules from the kernel.
15
16 //applet:IF_RMMOD(IF_NOT_MODPROBE_SMALL(APPLET_NOEXEC(rmmod, rmmod, BB_DIR_SBIN, BB_SUID_DROP, rmmod)))
17
18 //kbuild:ifneq ($(CONFIG_MODPROBE_SMALL),y)
19 //kbuild:lib-$(CONFIG_RMMOD) += rmmod.o modutils.o
20 //kbuild:endif
21
22 //usage:#if !ENABLE_MODPROBE_SMALL
23 //usage:#define rmmod_trivial_usage
24 //usage: "[-wfa] [MODULE]..."
25 //usage:#define rmmod_full_usage "\n\n"
26 //usage: "Unload kernel modules\n"
27 //usage: "\n -w Wait until the module is no longer used"
28 //usage: "\n -f Force unload"
29 //usage: "\n -a Remove all unused modules (recursively)"
30 //usage:#define rmmod_example_usage
31 //usage: "$ rmmod tulip\n"
32 //usage:#endif
33
34 #include "libbb.h"
35 #include "modutils.h"
36
37 int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
rmmod_main(int argc UNUSED_PARAM,char ** argv)38 int rmmod_main(int argc UNUSED_PARAM, char **argv)
39 {
40 int n, err;
41 unsigned flags = O_NONBLOCK | O_EXCL;
42
43 /* Parse command line. */
44 n = getopt32(argv, "wfas"); // -s ignored
45 argv += optind;
46 if (n & 1) // --wait
47 flags &= ~O_NONBLOCK;
48 if (n & 2) // --force
49 flags |= O_TRUNC;
50 if (n & 4) {
51 /* Unload _all_ unused modules via NULL delete_module() call */
52 err = bb_delete_module(NULL, flags);
53 if (err && err != EFAULT)
54 bb_simple_perror_msg_and_die("rmmod");
55 return EXIT_SUCCESS;
56 }
57
58 if (!*argv)
59 bb_show_usage();
60
61 n = ENABLE_FEATURE_2_4_MODULES && get_linux_version_code() < KERNEL_VERSION(2,6,0);
62 while (*argv) {
63 char modname[MODULE_NAME_LEN];
64 const char *bname;
65
66 bname = bb_basename(*argv++);
67 if (n)
68 safe_strncpy(modname, bname, MODULE_NAME_LEN);
69 else
70 filename2modname(bname, modname);
71 err = bb_delete_module(modname, flags);
72 if (err)
73 bb_perror_msg_and_die("can't unload module '%s'",
74 modname);
75 }
76
77 return EXIT_SUCCESS;
78 }
79