lsmod.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  12. */
  13. #include "libbb.h"
  14. #if !ENABLE_FEATURE_CHECK_TAINTED_MODULE
  15. static void check_tainted(void) { bb_putchar('\n'); }
  16. #else
  17. #define TAINT_FILENAME "/proc/sys/kernel/tainted"
  18. #define TAINT_PROPRIETORY_MODULE (1<<0)
  19. #define TAINT_FORCED_MODULE (1<<1)
  20. #define TAINT_UNSAFE_SMP (1<<2)
  21. static void check_tainted(void)
  22. {
  23. int tainted;
  24. FILE *f;
  25. tainted = 0;
  26. f = fopen(TAINT_FILENAME, "r");
  27. if (f) {
  28. fscanf(f, "%d", &tainted);
  29. fclose(f);
  30. }
  31. if (tainted) {
  32. printf(" Tainted: %c%c%c\n",
  33. tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
  34. tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
  35. tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
  36. } else {
  37. printf(" Not tainted\n");
  38. }
  39. }
  40. #endif
  41. #if ENABLE_FEATURE_QUERY_MODULE_INTERFACE
  42. struct module_info
  43. {
  44. unsigned long addr;
  45. unsigned long size;
  46. unsigned long flags;
  47. long usecount;
  48. };
  49. int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
  50. enum {
  51. /* Values for query_module's which. */
  52. QM_MODULES = 1,
  53. QM_DEPS = 2,
  54. QM_REFS = 3,
  55. QM_SYMBOLS = 4,
  56. QM_INFO = 5,
  57. /* Bits of module.flags. */
  58. NEW_MOD_RUNNING = 1,
  59. NEW_MOD_DELETED = 2,
  60. NEW_MOD_AUTOCLEAN = 4,
  61. NEW_MOD_VISITED = 8,
  62. NEW_MOD_USED_ONCE = 16,
  63. NEW_MOD_INITIALIZING = 64
  64. };
  65. int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  66. int lsmod_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
  67. {
  68. struct module_info info;
  69. char *module_names, *mn, *deps, *dn;
  70. size_t bufsize, depsize, nmod, count, i, j;
  71. module_names = deps = NULL;
  72. bufsize = depsize = 0;
  73. while (query_module(NULL, QM_MODULES, module_names, bufsize, &nmod)) {
  74. if (errno != ENOSPC) bb_perror_msg_and_die("QM_MODULES");
  75. module_names = xmalloc(bufsize = nmod);
  76. }
  77. deps = xmalloc(depsize = 256);
  78. printf("Module\t\t\tSize Used by");
  79. check_tainted();
  80. for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) {
  81. if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) {
  82. if (errno == ENOENT) {
  83. /* The module was removed out from underneath us. */
  84. continue;
  85. }
  86. /* else choke */
  87. bb_perror_msg_and_die("module %s: QM_INFO", mn);
  88. }
  89. while (query_module(mn, QM_REFS, deps, depsize, &count)) {
  90. if (errno == ENOENT) {
  91. /* The module was removed out from underneath us. */
  92. continue;
  93. } else if (errno != ENOSPC)
  94. bb_perror_msg_and_die("module %s: QM_REFS", mn);
  95. deps = xrealloc(deps, count);
  96. }
  97. printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
  98. if (info.flags & NEW_MOD_DELETED)
  99. printf(" (deleted)");
  100. else if (info.flags & NEW_MOD_INITIALIZING)
  101. printf(" (initializing)");
  102. else if (!(info.flags & NEW_MOD_RUNNING))
  103. printf(" (uninitialized)");
  104. else {
  105. if (info.flags & NEW_MOD_AUTOCLEAN)
  106. printf(" (autoclean) ");
  107. if (!(info.flags & NEW_MOD_USED_ONCE))
  108. printf(" (unused)");
  109. }
  110. if (count) printf(" [");
  111. for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
  112. printf("%s%s", dn, (j==count-1)? "":" ");
  113. }
  114. if (count) printf("]");
  115. bb_putchar('\n');
  116. }
  117. #if ENABLE_FEATURE_CLEAN_UP
  118. free(module_names);
  119. #endif
  120. return 0;
  121. }
  122. #else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
  123. int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  124. int lsmod_main(int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
  125. {
  126. FILE *file = xfopen("/proc/modules", "r");
  127. printf("Module Size Used by");
  128. check_tainted();
  129. #if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
  130. {
  131. char *line;
  132. while ((line = xmalloc_fgets(file)) != NULL) {
  133. char *tok;
  134. tok = strtok(line, " \t");
  135. printf("%-19s", tok);
  136. tok = strtok(NULL, " \t\n");
  137. printf(" %8s", tok);
  138. tok = strtok(NULL, " \t\n");
  139. /* Null if no module unloading support. */
  140. if (tok) {
  141. printf(" %s", tok);
  142. tok = strtok(NULL, "\n");
  143. if (!tok)
  144. tok = (char*)"";
  145. /* New-style has commas, or -. If so,
  146. truncate (other fields might follow). */
  147. else if (strchr(tok, ',')) {
  148. tok = strtok(tok, "\t ");
  149. /* Strip trailing comma. */
  150. if (tok[strlen(tok)-1] == ',')
  151. tok[strlen(tok)-1] = '\0';
  152. } else if (tok[0] == '-'
  153. && (tok[1] == '\0' || isspace(tok[1]))
  154. ) {
  155. tok = (char*)"";
  156. }
  157. printf(" %s", tok);
  158. }
  159. bb_putchar('\n');
  160. free(line);
  161. }
  162. fclose(file);
  163. }
  164. #else
  165. xprint_and_close_file(file);
  166. #endif /* CONFIG_FEATURE_2_6_MODULES */
  167. return EXIT_SUCCESS;
  168. }
  169. #endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */