51390eb830a0090c98185eba6d26e91077ccb776
[oweals/busybox.git] / modutils / rmmod.c
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
11 //applet:IF_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_DROP))
12
13 #include "libbb.h"
14 #include "modutils.h"
15
16 int rmmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
17 int rmmod_main(int argc UNUSED_PARAM, char **argv)
18 {
19         int n;
20         unsigned flags = O_NONBLOCK | O_EXCL;
21
22         /* Parse command line. */
23         n = getopt32(argv, "wfas"); // -s ignored
24         argv += optind;
25         if (n & 1)      // --wait
26                 flags &= ~O_NONBLOCK;
27         if (n & 2)      // --force
28                 flags |= O_TRUNC;
29         if (n & 4) {
30                 /* Unload _all_ unused modules via NULL delete_module() call */
31                 if (bb_delete_module(NULL, flags) != 0 && errno != EFAULT)
32                         bb_perror_msg_and_die("rmmod");
33                 return EXIT_SUCCESS;
34         }
35
36         if (!*argv)
37                 bb_show_usage();
38
39         n = ENABLE_FEATURE_2_4_MODULES && get_linux_version_code() < KERNEL_VERSION(2,6,0);
40         while (*argv) {
41                 char modname[MODULE_NAME_LEN];
42                 const char *bname;
43
44                 bname = bb_basename(*argv++);
45                 if (n)
46                         safe_strncpy(modname, bname, MODULE_NAME_LEN);
47                 else
48                         filename2modname(bname, modname);
49                 if (bb_delete_module(modname, flags))
50                         bb_error_msg_and_die("can't unload '%s': %s",
51                                              modname, moderror(errno));
52         }
53
54         return EXIT_SUCCESS;
55 }