lsmod.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. enum {
  76. /* Values for query_module's which. */
  77. QM_MODULES = 1,
  78. QM_DEPS = 2,
  79. QM_REFS = 3,
  80. QM_SYMBOLS = 4,
  81. QM_INFO = 5,
  82. /* Bits of module.flags. */
  83. NEW_MOD_RUNNING = 1,
  84. NEW_MOD_DELETED = 2,
  85. NEW_MOD_AUTOCLEAN = 4,
  86. NEW_MOD_VISITED = 8,
  87. NEW_MOD_USED_ONCE = 16,
  88. NEW_MOD_INITIALIZING = 64
  89. };
  90. int lsmod_main(int argc, char **argv)
  91. {
  92. struct module_info info;
  93. char *module_names, *mn, *deps, *dn;
  94. size_t bufsize, depsize, nmod, count, i, j;
  95. module_names = xmalloc(bufsize = 256);
  96. if (my_query_module(NULL, QM_MODULES, (void **)&module_names, &bufsize,
  97. &nmod)) {
  98. bb_perror_msg_and_die("QM_MODULES");
  99. }
  100. deps = xmalloc(depsize = 256);
  101. printf("Module Size Used by");
  102. check_tainted();
  103. for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
  104. if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
  105. if (errno == ENOENT) {
  106. /* The module was removed out from underneath us. */
  107. continue;
  108. }
  109. /* else choke */
  110. bb_perror_msg_and_die("module %s: QM_INFO", mn);
  111. }
  112. if (my_query_module(mn, QM_REFS, (void **)&deps, &depsize, &count)) {
  113. if (errno == ENOENT) {
  114. /* The module was removed out from underneath us. */
  115. continue;
  116. }
  117. bb_perror_msg_and_die("module %s: QM_REFS", mn);
  118. }
  119. printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
  120. if (info.flags & NEW_MOD_DELETED)
  121. printf(" (deleted)");
  122. else if (info.flags & NEW_MOD_INITIALIZING)
  123. printf(" (initializing)");
  124. else if (!(info.flags & NEW_MOD_RUNNING))
  125. printf(" (uninitialized)");
  126. else {
  127. if (info.flags & NEW_MOD_AUTOCLEAN)
  128. printf(" (autoclean) ");
  129. if (!(info.flags & NEW_MOD_USED_ONCE))
  130. printf(" (unused)");
  131. }
  132. if (count) printf(" [");
  133. for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
  134. printf("%s%s", dn, (j==count-1)? "":" ");
  135. }
  136. if (count) printf("]");
  137. printf("\n");
  138. }
  139. #ifdef CONFIG_FEATURE_CLEAN_UP
  140. free(module_names);
  141. #endif
  142. return( 0);
  143. }
  144. #else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
  145. int lsmod_main(int argc, char **argv)
  146. {
  147. printf("Module Size Used by");
  148. check_tainted();
  149. #if defined(CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT)
  150. {
  151. FILE *file;
  152. char line[4096];
  153. file = bb_xfopen("/proc/modules", "r");
  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 */