aboutsummaryrefslogtreecommitdiff
path: root/modutils/lsmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'modutils/lsmod.c')
-rw-r--r--modutils/lsmod.c201
1 files changed, 43 insertions, 158 deletions
diff --git a/modutils/lsmod.c b/modutils/lsmod.c
index 3f237039e..b66563693 100644
--- a/modutils/lsmod.c
+++ b/modutils/lsmod.c
@@ -3,192 +3,77 @@
3 * Mini lsmod implementation for busybox 3 * Mini lsmod implementation for busybox
4 * 4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 * 6 * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
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 * 7 *
11 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
12 */ 9 */
13 10
14#include "libbb.h" 11#include "libbb.h"
15 12
16 13#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
17#if !ENABLE_FEATURE_CHECK_TAINTED_MODULE 14enum {
18static void check_tainted(void) { bb_putchar('\n'); } 15 TAINT_PROPRIETORY_MODULE = (1 << 0),
19#else 16 TAINT_FORCED_MODULE = (1 << 1),
20#define TAINT_FILENAME "/proc/sys/kernel/tainted" 17 TAINT_UNSAFE_SMP = (1 << 2),
21#define TAINT_PROPRIETORY_MODULE (1<<0) 18};
22#define TAINT_FORCED_MODULE (1<<1)
23#define TAINT_UNSAFE_SMP (1<<2)
24 19
25static void check_tainted(void) 20static void check_tainted(void)
26{ 21{
27 int tainted; 22 int tainted = 0;
28 FILE *f; 23 char *buf = xmalloc_open_read_close("/proc/sys/kernel/tainted", NULL);
29 24 if (buf) {
30 tainted = 0; 25 tainted = atoi(buf);
31 f = fopen_for_read(TAINT_FILENAME); 26 if (ENABLE_FEATURE_CLEAN_UP)
32 if (f) { 27 free(buf);
33 fscanf(f, "%d", &tainted);
34 fclose(f);
35 } 28 }
29
36 if (tainted) { 30 if (tainted) {
37 printf(" Tainted: %c%c%c\n", 31 printf(" Tainted: %c%c%c\n",
38 tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G', 32 tainted & TAINT_PROPRIETORY_MODULE ? 'P' : 'G',
39 tainted & TAINT_FORCED_MODULE ? 'F' : ' ', 33 tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
40 tainted & TAINT_UNSAFE_SMP ? 'S' : ' '); 34 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ');
41 } else { 35 } else {
42 printf(" Not tainted\n"); 36 puts(" Not tainted");
43 } 37 }
44} 38}
39#else
40static void check_tainted(void) { putchar('\n'); }
45#endif 41#endif
46 42
47#if ENABLE_FEATURE_QUERY_MODULE_INTERFACE
48
49struct module_info
50{
51 unsigned long addr;
52 unsigned long size;
53 unsigned long flags;
54 long usecount;
55};
56
57
58int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
59
60enum {
61/* Values for query_module's which. */
62 QM_MODULES = 1,
63 QM_DEPS = 2,
64 QM_REFS = 3,
65 QM_SYMBOLS = 4,
66 QM_INFO = 5,
67
68/* Bits of module.flags. */
69 NEW_MOD_RUNNING = 1,
70 NEW_MOD_DELETED = 2,
71 NEW_MOD_AUTOCLEAN = 4,
72 NEW_MOD_VISITED = 8,
73 NEW_MOD_USED_ONCE = 16,
74 NEW_MOD_INITIALIZING = 64
75};
76
77int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 43int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
78int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 44int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
79{ 45{
80 struct module_info info; 46#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
81 char *module_names, *mn, *deps, *dn; 47 char *token[4];
82 size_t bufsize, depsize, nmod, count, i, j; 48 parser_t *parser = config_open("/proc/modules");
83 49 printf("Module Size Used by"); //vda!
84 module_names = deps = NULL;
85 bufsize = depsize = 0;
86 while (query_module(NULL, QM_MODULES, module_names, bufsize, &nmod)) {
87 if (errno != ENOSPC) bb_perror_msg_and_die("QM_MODULES");
88 module_names = xmalloc(bufsize = nmod);
89 }
90
91 deps = xmalloc(depsize = 256);
92 printf("Module\t\t\tSize Used by");
93 check_tainted(); 50 check_tainted();
94 51
95 for (i = 0, mn = module_names; i < nmod; mn += strlen(mn) + 1, i++) { 52 if (ENABLE_FEATURE_2_4_MODULES
96 if (query_module(mn, QM_INFO, &info, sizeof(info), &count)) { 53 && get_linux_version_code() < KERNEL_VERSION(2,6,0)
97 if (errno == ENOENT) { 54 ) {
98 /* The module was removed out from underneath us. */ 55 while (config_read(parser, token, 4, 3, "# \t", PARSE_NORMAL)) {
99 continue; 56 if (token[3] != NULL && token[3][0] == '[') {
100 } 57 token[3]++;
101 /* else choke */ 58 token[3][strlen(token[3])-1] = '\0';
102 bb_perror_msg_and_die("module %s: QM_INFO", mn); 59 } else
60 token[3] = (char *) "";
61 printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
103 } 62 }
104 while (query_module(mn, QM_REFS, deps, depsize, &count)) { 63 } else {
105 if (errno == ENOENT) { 64 while (config_read(parser, token, 4, 4, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) {
106 /* The module was removed out from underneath us. */ 65 // N.B. token[3] is either '-' (module is not used by others)
107 continue; 66 // or comma-separated list ended by comma
108 } else if (errno != ENOSPC) 67 // so trimming the trailing char is just what we need!
109 bb_perror_msg_and_die("module %s: QM_REFS", mn); 68 token[3][strlen(token[3])-1] = '\0';
110 deps = xrealloc(deps, count); 69 printf("%-19s %8s %2s %s\n", token[0], token[1], token[2], token[3]);
111 }
112 printf("%-20s%8lu%4ld", mn, info.size, info.usecount);
113 if (info.flags & NEW_MOD_DELETED)
114 printf(" (deleted)");
115 else if (info.flags & NEW_MOD_INITIALIZING)
116 printf(" (initializing)");
117 else if (!(info.flags & NEW_MOD_RUNNING))
118 printf(" (uninitialized)");
119 else {
120 if (info.flags & NEW_MOD_AUTOCLEAN)
121 printf(" (autoclean) ");
122 if (!(info.flags & NEW_MOD_USED_ONCE))
123 printf(" (unused)");
124 }
125 if (count)
126 printf(" [");
127 for (j = 0, dn = deps; j < count; dn += strlen(dn) + 1, j++) {
128 printf("%s%s", dn, (j==count-1)? "":" ");
129 }
130 if (count)
131 bb_putchar(']');
132
133 bb_putchar('\n');
134 }
135
136#if ENABLE_FEATURE_CLEAN_UP
137 free(module_names);
138#endif
139
140 return 0;
141}
142
143#else /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */
144
145int lsmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
146int lsmod_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
147{
148 FILE *file = xfopen_for_read("/proc/modules");
149
150 printf("Module Size Used by");
151 check_tainted();
152#if ENABLE_FEATURE_LSMOD_PRETTY_2_6_OUTPUT
153 {
154 char *line;
155 while ((line = xmalloc_fgets(file)) != NULL) {
156 char *tok;
157
158 tok = strtok(line, " \t");
159 printf("%-19s", tok);
160 tok = strtok(NULL, " \t\n");
161 printf(" %8s", tok);
162 tok = strtok(NULL, " \t\n");
163 /* Null if no module unloading support. */
164 if (tok) {
165 printf(" %s", tok);
166 tok = strtok(NULL, "\n");
167 if (!tok)
168 tok = (char*)"";
169 /* New-style has commas, or -. If so,
170 truncate (other fields might follow). */
171 else if (strchr(tok, ',')) {
172 tok = strtok(tok, "\t ");
173 /* Strip trailing comma. */
174 if (tok[strlen(tok)-1] == ',')
175 tok[strlen(tok)-1] = '\0';
176 } else if (tok[0] == '-'
177 && (tok[1] == '\0' || isspace(tok[1]))
178 ) {
179 tok = (char*)"";
180 }
181 printf(" %s", tok);
182 }
183 bb_putchar('\n');
184 free(line);
185 } 70 }
186 fclose(file);
187 } 71 }
72 if (ENABLE_FEATURE_CLEAN_UP)
73 config_close(parser);
188#else 74#else
189 xprint_and_close_file(file); 75 check_tainted();
190#endif /* CONFIG_FEATURE_2_6_MODULES */ 76 xprint_and_close_file(xfopen_for_read("/proc/modules"));
77#endif
191 return EXIT_SUCCESS; 78 return EXIT_SUCCESS;
192} 79}
193
194#endif /* CONFIG_FEATURE_QUERY_MODULE_INTERFACE */