lsmod.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini lsmod implementation for busybox
  4. *
  5. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  6. *
  7. * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
  8. * Nicolas Ferre <nicolas.ferre@alcove.fr> to support pre 2.1 kernels
  9. * (which lack the query_module() interface).
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  24. *
  25. */
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stddef.h>
  30. #include <errno.h>
  31. #include <unistd.h>
  32. #include <dirent.h>
  33. #include <ctype.h>
  34. #include <assert.h>
  35. #include <getopt.h>
  36. #include <sys/utsname.h>
  37. #include <sys/file.h>
  38. #include "busybox.h"
  39. #ifndef CONFIG_FEATURE_CHECK_TAINTED_MODULE
  40. static inline void check_tainted(void) { printf("\n"); }
  41. #else
  42. #define TAINT_FILENAME "/proc/sys/kernel/tainted"
  43. #define TAINT_PROPRIETORY_MODULE (1<<0)
  44. #define TAINT_FORCED_MODULE (1<<1)
  45. #define TAINT_UNSAFE_SMP (1<<2)
  46. static void check_tainted(void)
  47. {
  48. int tainted;
  49. FILE *f;
  50. tainted = 0;
  51. if ((f = fopen(TAINT_FILENAME, "r"))) {
  52. fscanf(f, "%d", &tainted);
  53. fclose(f);
  54. }
  55. if (f && tainted) {
  56. printf(" Tainted: %c%c%c\n",
  57. tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
  58. tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
  59. tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
  60. }
  61. else {
  62. printf(" Not tainted\n");
  63. }
  64. }
  65. #endif
  66. #ifdef CONFIG_FEATURE_QUERY_MODULE_INTERFACE
  67. struct module_info
  68. {
  69. unsigned long addr;
  70. unsigned long size;
  71. unsigned long flags;
  72. long usecount;
  73. };
  74. int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
  75. /* Values for query_module's which. */
  76. static const int QM_MODULES = 1;
  77. static const int QM_DEPS = 2;
  78. static const int QM_REFS = 3;
  79. static const int QM_SYMBOLS = 4;
  80. static const int QM_INFO = 5;
  81. /* Bits of module.flags. */
  82. static const int NEW_MOD_RUNNING = 1;
  83. static const int NEW_MOD_DELETED = 2;
  84. static const int NEW_MOD_AUTOCLEAN = 4;
  85. static const int NEW_MOD_VISITED = 8;
  86. static const int NEW_MOD_USED_ONCE = 16;
  87. static const int NEW_MOD_INITIALIZING = 64;
  88. extern int lsmod_main(int argc, char **argv)
  89. {
  90. struct module_info info;
  91. char *module_names, *mn, *deps, *dn;
  92. size_t bufsize, depsize, nmod, count, i, j;
  93. module_names = xmalloc(bufsize = 256);
  94. if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize,
  95. &nmod)) {
  96. bb_perror_msg_and_die("QM_MODULES");
  97. }
  98. deps = xmalloc(depsize = 256);
  99. printf("Module Size Used by");
  100. check_tainted();
  101. for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
  102. if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
  103. if (errno == ENOENT) {
  104. /* The module was removed out from underneath us. */
  105. continue;
  106. }
  107. /* else choke */
  108. bb_perror_msg_and_die("module %s: QM_INFO", mn);
  109. }
  110. if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
  111. if (errno == ENOENT) {
  112. /* The module was removed out from underneath us. */
  113. continue;
  114. }
  115. bb_perror_msg_and_die("module %s: QM_REFS", mn);
  116. }
  117. printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
  118. if (info.flags & NEW_MOD_DELETED)
  119. printf(" (deleted)");
  120. else if (info.flags & NEW_MOD_INITIALIZING)
  121. printf(" (initializing)");
  122. else if (!(info.flags & NEW_MOD_RUNNING))
  123. printf(" (uninitialized)");
  124. else {
  125. if (info.flags & NEW_MOD_AUTOCLEAN)
  126. printf(" (autoclean) ");
  127. if (!(info.flags & NEW_MOD_USED_ONCE))
  128. printf(" (unused)");
  129. }
  130. if (count) printf(" [");
  131. for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
  132. printf("%s%s", dn, (j==count-1)? "":" ");
  133. }
  134. if (count) printf("]");
  135. printf("\n");
  136. }
  137. #ifdef CONFIG_FEATURE_CLEAN_UP
  138. free(module_names);
  139. #endif
  140. return( 0);
  141. }
  142. #else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
  143. extern int lsmod_main(int argc, char **argv)
  144. {
  145. printf("Module Size Used by");
  146. check_tainted();
  147. if (bb_xprint_file_by_name("/proc/modules") < 0) {
  148. return 0;
  149. }
  150. return 1;
  151. }
  152. #endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */