lsmod.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT)
  148. {
  149. FILE *file;
  150. char line[4096];
  151. file = fopen("/proc/modules", "r");
  152. if (!file)
  153. bb_error_msg_and_die("Opening /proc/modules");
  154. while (fgets(line, sizeof(line), file)) {
  155. char *tok;
  156. tok = strtok(line, " \t");
  157. printf("%-19s", tok);
  158. tok = strtok(NULL, " \t\n");
  159. printf(" %8s", tok);
  160. tok = strtok(NULL, " \t\n");
  161. /* Null if no module unloading support. */
  162. if (tok) {
  163. printf(" %s", tok);
  164. tok = strtok(NULL, "\n");
  165. if (!tok)
  166. tok = "";
  167. /* New-style has commas, or -. If so,
  168. truncate (other fields might follow). */
  169. else if (strchr(tok, ',')) {
  170. tok = strtok(tok, "\t ");
  171. /* Strip trailing comma. */
  172. if (tok[strlen(tok)-1] == ',')
  173. tok[strlen(tok)-1] = '\0';
  174. } else if (tok[0] == '-'
  175. && (tok[1] == '\0' || isspace(tok[1])))
  176. tok = "";
  177. printf(" %s", tok);
  178. }
  179. printf("\n");
  180. }
  181. fclose(file);
  182. }
  183. return 0; /* Success */
  184. #else
  185. if (bb_xprint_file_by_name("/proc/modules") < 0) {
  186. return 0;
  187. }
  188. #endif /* CONFIG_FEATURE_2_6_MODULES */
  189. return 1;
  190. }
  191. #endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */