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 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10#include "libbb.h" 11#include <sys/syscall.h> 12 13#if ENABLE_FEATURE_2_6_MODULES 14static inline void filename2modname(char *modname, const char *afterslash) 15{ 16 unsigned int i; 17 int kr_chk = 1; 18 19 if (ENABLE_FEATURE_2_4_MODULES 20 && get_linux_version_code() <= KERNEL_VERSION(2,6,0)) 21 kr_chk = 0; 22 23 /* Convert to underscores, stop at first . */ 24 for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) { 25 if (kr_chk && (afterslash[i] == '-')) 26 modname[i] = '_'; 27 else 28 modname[i] = afterslash[i]; 29 } 30 modname[i] = '\0'; 31} 32#else 33void filename2modname(char *modname, const char *afterslash); 34#endif 35 36// There really should be a header file for this... 37 38int query_module(const char *name, int which, void *buf, 39 size_t bufsize, size_t *ret); 40 41int rmmod_main(int argc, char **argv); 42int rmmod_main(int argc, char **argv) 43{ 44 int n, ret = EXIT_SUCCESS; 45 unsigned int flags = O_NONBLOCK|O_EXCL; 46 47#define misc_buf bb_common_bufsiz1 48 49 /* Parse command line. */ 50 n = getopt32(argv, "wfa"); 51 if (n & 1) // --wait 52 flags &= ~O_NONBLOCK; 53 if (n & 2) // --force 54 flags |= O_TRUNC; 55 if (n & 4) { 56 /* Unload _all_ unused modules via NULL delete_module() call */ 57 /* until the number of modules does not change */ 58 size_t nmod = 0; /* number of modules */ 59 size_t pnmod = -1; /* previous number of modules */ 60 61 while (nmod != pnmod) { 62 if (syscall(__NR_delete_module, NULL, flags) != 0) { 63 if (errno == EFAULT) 64 return ret; 65 bb_perror_msg_and_die("rmmod"); 66 } 67 pnmod = nmod; 68 // the 1 here is QM_MODULES. 69 if (ENABLE_FEATURE_QUERY_MODULE_INTERFACE && query_module(NULL, 70 1, misc_buf, sizeof(misc_buf), 71 &nmod)) 72 { 73 bb_perror_msg_and_die("QM_MODULES"); 74 } 75 } 76 return EXIT_SUCCESS; 77 } 78 79 if (optind == argc) 80 bb_show_usage(); 81 82 for (n = optind; n < argc; n++) { 83 if (ENABLE_FEATURE_2_6_MODULES) { 84 filename2modname(misc_buf, bb_basename(argv[n])); 85 } 86 87 if (syscall(__NR_delete_module, ENABLE_FEATURE_2_6_MODULES ? misc_buf : argv[n], flags)) { 88 bb_perror_msg("%s", argv[n]); 89 ret = EXIT_FAILURE; 90 } 91 } 92 93 return ret; 94} 95