diff --git a/docs/busybox.sgml b/docs/busybox.sgml index aa3c37692..dacc13249 100644 --- a/docs/busybox.sgml +++ b/docs/busybox.sgml @@ -2788,7 +2788,7 @@ - -a Try to remove all unused kernel modules + -a Remove all unused modules (recursively) diff --git a/include/libbb.h b/include/libbb.h index 5f437a95f..3523cc410 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -357,6 +357,8 @@ typedef struct { extern procps_status_t * procps_scan(int save_user_arg0); extern unsigned short compare_string_array(const char *string_array[], const char *key); +extern int my_query_module(const char *name, int which, void **buf, size_t *bufsize, size_t *ret); + typedef struct llist_s { char *data; struct llist_s *link; diff --git a/include/usage.h b/include/usage.h index 3b519e65d..16dd6fd78 100644 --- a/include/usage.h +++ b/include/usage.h @@ -1722,7 +1722,7 @@ #define rmmod_full_usage \ "Unloads the specified kernel modules from the kernel.\n\n" \ "Options:\n" \ - "\t-a\tTry to remove all unused kernel modules." + "\t-a\tRemove all unused modules (recursively)" #define rmmod_example_usage \ "$ rmmod tulip\n" diff --git a/libbb/Makefile.in b/libbb/Makefile.in index 3f4e77314..c97f7d2b3 100644 --- a/libbb/Makefile.in +++ b/libbb/Makefile.in @@ -38,7 +38,7 @@ LIBBB_SRC:= \ my_getpwnam.c my_getpwnamegid.c my_getpwuid.c obscure.c parse_mode.c \ parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \ process_escape_sequence.c procps.c pwd2spwd.c pw_encrypt.c \ - read_package_field.c recursive_action.c remove_file.c \ + qmodule.c read_package_field.c recursive_action.c remove_file.c \ restricted_shell.c run_parts.c run_shell.c safe_read.c safe_strncpy.c \ setup_environment.c simplify_path.c syscalls.c syslog_msg_with_name.c \ time_string.c trim.c u_signal_names.c vdprintf.c verror_msg.c \ diff --git a/libbb/qmodule.c b/libbb/qmodule.c new file mode 100644 index 000000000..fd14d10fa --- /dev/null +++ b/libbb/qmodule.c @@ -0,0 +1,29 @@ +/* + Copyright (C) 2002 Tim Riker + everyone seems to claim it someplace. ;-) +*/ + +#include + +#include "libbb.h" + +int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); + +int my_query_module(const char *name, int which, void **buf, + size_t *bufsize, size_t *ret) +{ + int my_ret; + + my_ret = query_module(name, which, *buf, *bufsize, ret); + + if (my_ret == -1 && errno == ENOSPC) { + *buf = xrealloc(*buf, *ret); + *bufsize = *ret; + + my_ret = query_module(name, which, *buf, *bufsize, ret); + } + + return my_ret; +} + + diff --git a/modutils/lsmod.c b/modutils/lsmod.c index d51da2d16..0d5ac756b 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c @@ -98,23 +98,6 @@ static const int NEW_MOD_VISITED = 8; static const int NEW_MOD_USED_ONCE = 16; static const int NEW_MOD_INITIALIZING = 64; -static int my_query_module(const char *name, int which, void **buf, - size_t *bufsize, size_t *ret) -{ - int my_ret; - - my_ret = query_module(name, which, *buf, *bufsize, ret); - - if (my_ret == -1 && errno == ENOSPC) { - *buf = xrealloc(*buf, *ret); - *bufsize = *ret; - - my_ret = query_module(name, which, *buf, *bufsize, ret); - } - - return my_ret; -} - extern int lsmod_main(int argc, char **argv) { struct module_info info; diff --git a/modutils/rmmod.c b/modutils/rmmod.c index affe975fa..0103d9145 100644 --- a/modutils/rmmod.c +++ b/modutils/rmmod.c @@ -34,14 +34,30 @@ extern int delete_module(const char * name); extern int rmmod_main(int argc, char **argv) { int n, ret = EXIT_SUCCESS; + size_t nmod = 0; /* number of modules */ + size_t pnmod = -1; /* previous number of modules */ + void *buf; /* hold the module names which we ignore but must get */ + size_t bufsize = 0; /* Parse command line. */ while ((n = getopt(argc, argv, "a")) != EOF) { switch (n) { case 'a': /* Unload _all_ unused modules via NULL delete_module() call */ - if (delete_module(NULL)) - perror_msg_and_die("rmmod"); + /* until the number of modules does not change */ + buf = xmalloc(bufsize = 256); + while (nmod != pnmod) { + if (delete_module(NULL)) + perror_msg_and_die("rmmod"); + pnmod = nmod; + /* 1 == QM_MODULES */ + if (my_query_module(NULL, 1, &buf, &bufsize, &nmod)) { + perror_msg_and_die("QM_MODULES"); + } + } +#ifdef CONFIG_FEATURE_CLEAN_UP + free(buf); +#endif return EXIT_SUCCESS; default: show_usage();