rmmod.c 2.4 KB

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