diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-17 18:46:06 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-06-17 18:46:06 +0200 |
| commit | ee47f6e44f1a33146e26c7410ade10a98f78ead1 (patch) | |
| tree | 0d86e43e6c6162dbf64f9bf01374abaffec3179b /modutils | |
| parent | a5bdbe10877e2e53aaba051eddfd5d47520657f5 (diff) | |
| download | busybox-w32-ee47f6e44f1a33146e26c7410ade10a98f78ead1.tar.gz busybox-w32-ee47f6e44f1a33146e26c7410ade10a98f78ead1.tar.bz2 busybox-w32-ee47f6e44f1a33146e26c7410ade10a98f78ead1.zip | |
modprobe: correct exitcode handling and error messages with respect to -q
function old new delta
do_modprobe 319 339 +20
bb_delete_module 10 26 +16
moderror 62 71 +9
bb_init_module 112 119 +7
modprobe_main 488 494 +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/0 up/down: 58/0) Total: 58 bytes
Signed-off-by: Gilles Espinasse <g.esp@free.fr>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'modutils')
| -rw-r--r-- | modutils/modprobe.c | 159 | ||||
| -rw-r--r-- | modutils/modutils.c | 65 | ||||
| -rw-r--r-- | modutils/modutils.h | 12 |
3 files changed, 143 insertions, 93 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index d000c9123..cfc16cb34 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
| @@ -9,10 +9,9 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), | 11 | /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), |
| 12 | * we expect the full dependency list to be specified in modules.dep. Older | 12 | * we expect the full dependency list to be specified in modules.dep. |
| 13 | * versions would only export the direct dependency list. | 13 | * Older versions would only export the direct dependency list. |
| 14 | */ | 14 | */ |
| 15 | |||
| 16 | #include "libbb.h" | 15 | #include "libbb.h" |
| 17 | #include "modutils.h" | 16 | #include "modutils.h" |
| 18 | #include <sys/utsname.h> | 17 | #include <sys/utsname.h> |
| @@ -21,11 +20,11 @@ | |||
| 21 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) | 20 | //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) |
| 22 | #define DBG(...) ((void)0) | 21 | #define DBG(...) ((void)0) |
| 23 | 22 | ||
| 24 | #define MODULE_FLAG_LOADED 0x0001 | 23 | #define MODULE_FLAG_LOADED 0x0001 |
| 25 | #define MODULE_FLAG_NEED_DEPS 0x0002 | 24 | #define MODULE_FLAG_NEED_DEPS 0x0002 |
| 26 | /* "was seen in modules.dep": */ | 25 | /* "was seen in modules.dep": */ |
| 27 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 | 26 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 |
| 28 | #define MODULE_FLAG_BLACKLISTED 0x0008 | 27 | #define MODULE_FLAG_BLACKLISTED 0x0008 |
| 29 | 28 | ||
| 30 | struct module_entry { /* I'll call it ME. */ | 29 | struct module_entry { /* I'll call it ME. */ |
| 31 | unsigned flags; | 30 | unsigned flags; |
| @@ -38,18 +37,30 @@ struct module_entry { /* I'll call it ME. */ | |||
| 38 | llist_t *deps; /* strings. modules we depend on */ | 37 | llist_t *deps; /* strings. modules we depend on */ |
| 39 | }; | 38 | }; |
| 40 | 39 | ||
| 40 | /* NB: INSMOD_OPT_SILENT bit suppresses ONLY non-existent modules, | ||
| 41 | * not deleted ones (those are still listed in modules.dep). | ||
| 42 | * module-init-tools version 3.4: | ||
| 43 | * # modprobe bogus | ||
| 44 | * FATAL: Module bogus not found. [exitcode 1] | ||
| 45 | * # modprobe -q bogus [silent, exitcode still 1] | ||
| 46 | * but: | ||
| 47 | * # rm kernel/drivers/net/dummy.ko | ||
| 48 | * # modprobe -q dummy | ||
| 49 | * FATAL: Could not open '/lib/modules/xxx/kernel/drivers/net/dummy.ko': No such file or directory | ||
| 50 | * [exitcode 1] | ||
| 51 | */ | ||
| 41 | #define MODPROBE_OPTS "acdlnrt:VC:" IF_FEATURE_MODPROBE_BLACKLIST("b") | 52 | #define MODPROBE_OPTS "acdlnrt:VC:" IF_FEATURE_MODPROBE_BLACKLIST("b") |
| 42 | enum { | 53 | enum { |
| 43 | MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ | 54 | MODPROBE_OPT_INSERT_ALL = (INSMOD_OPT_UNUSED << 0), /* a */ |
| 44 | MODPROBE_OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << 1), /* c */ | 55 | MODPROBE_OPT_DUMP_ONLY = (INSMOD_OPT_UNUSED << 1), /* c */ |
| 45 | MODPROBE_OPT_D = (INSMOD_OPT_UNUSED << 2), /* d */ | 56 | MODPROBE_OPT_D = (INSMOD_OPT_UNUSED << 2), /* d */ |
| 46 | MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 3), /* l */ | 57 | MODPROBE_OPT_LIST_ONLY = (INSMOD_OPT_UNUSED << 3), /* l */ |
| 47 | MODPROBE_OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << 4), /* n */ | 58 | MODPROBE_OPT_SHOW_ONLY = (INSMOD_OPT_UNUSED << 4), /* n */ |
| 48 | MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 5), /* r */ | 59 | MODPROBE_OPT_REMOVE = (INSMOD_OPT_UNUSED << 5), /* r */ |
| 49 | MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << 6), /* t */ | 60 | MODPROBE_OPT_RESTRICT = (INSMOD_OPT_UNUSED << 6), /* t */ |
| 50 | MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << 7), /* V */ | 61 | MODPROBE_OPT_VERONLY = (INSMOD_OPT_UNUSED << 7), /* V */ |
| 51 | MODPROBE_OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << 8), /* C */ | 62 | MODPROBE_OPT_CONFIGFILE = (INSMOD_OPT_UNUSED << 8), /* C */ |
| 52 | MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST, | 63 | MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST, |
| 53 | }; | 64 | }; |
| 54 | 65 | ||
| 55 | struct globals { | 66 | struct globals { |
| @@ -140,7 +151,7 @@ static int FAST_FUNC config_file_action(const char *filename, | |||
| 140 | { | 151 | { |
| 141 | char *tokens[3]; | 152 | char *tokens[3]; |
| 142 | parser_t *p; | 153 | parser_t *p; |
| 143 | struct module_entry *m; | 154 | struct module_entry *m; |
| 144 | int rc = TRUE; | 155 | int rc = TRUE; |
| 145 | 156 | ||
| 146 | if (bb_basename(filename)[0] == '.') | 157 | if (bb_basename(filename)[0] == '.') |
| @@ -199,7 +210,7 @@ static int FAST_FUNC config_file_action(const char *filename, | |||
| 199 | } | 210 | } |
| 200 | } | 211 | } |
| 201 | config_close(p); | 212 | config_close(p); |
| 202 | error: | 213 | error: |
| 203 | return rc; | 214 | return rc; |
| 204 | } | 215 | } |
| 205 | 216 | ||
| @@ -209,6 +220,11 @@ static int read_config(const char *path) | |||
| 209 | config_file_action, NULL, NULL, 1); | 220 | config_file_action, NULL, NULL, 1); |
| 210 | } | 221 | } |
| 211 | 222 | ||
| 223 | /* Return: similar to bb_init_module: | ||
| 224 | * 0 on success, | ||
| 225 | * -errno on open/read error, | ||
| 226 | * errno on init_module() error | ||
| 227 | */ | ||
| 212 | static int do_modprobe(struct module_entry *m) | 228 | static int do_modprobe(struct module_entry *m) |
| 213 | { | 229 | { |
| 214 | struct module_entry *m2 = m2; /* for compiler */ | 230 | struct module_entry *m2 = m2; /* for compiler */ |
| @@ -217,7 +233,8 @@ static int do_modprobe(struct module_entry *m) | |||
| 217 | llist_t *l; | 233 | llist_t *l; |
| 218 | 234 | ||
| 219 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { | 235 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { |
| 220 | DBG("skipping %s, not found in modules.dep", m->modname); | 236 | if (!(option_mask32 & INSMOD_OPT_SILENT)) |
| 237 | bb_error_msg("module %s not found in modules.dep", m->probed_name); | ||
| 221 | return -ENOENT; | 238 | return -ENOENT; |
| 222 | } | 239 | } |
| 223 | DBG("do_modprob'ing %s", m->modname); | 240 | DBG("do_modprob'ing %s", m->modname); |
| @@ -230,43 +247,52 @@ static int do_modprobe(struct module_entry *m) | |||
| 230 | 247 | ||
| 231 | first = 1; | 248 | first = 1; |
| 232 | rc = 0; | 249 | rc = 0; |
| 233 | while (m->deps && rc == 0) { | 250 | while (m->deps) { |
| 234 | fn = llist_pop(&m->deps); | 251 | rc = 0; |
| 252 | fn = llist_pop(&m->deps); /* we leak it */ | ||
| 235 | m2 = get_or_add_modentry(fn); | 253 | m2 = get_or_add_modentry(fn); |
| 254 | |||
| 236 | if (option_mask32 & MODPROBE_OPT_REMOVE) { | 255 | if (option_mask32 & MODPROBE_OPT_REMOVE) { |
| 256 | /* modprobe -r */ | ||
| 237 | if (m2->flags & MODULE_FLAG_LOADED) { | 257 | if (m2->flags & MODULE_FLAG_LOADED) { |
| 238 | if (bb_delete_module(m2->modname, O_EXCL) != 0) { | 258 | rc = bb_delete_module(m2->modname, O_EXCL); |
| 239 | if (first) | 259 | if (rc) { |
| 240 | rc = errno; | 260 | if (first) { |
| 261 | bb_error_msg("failed to unload module %s: %s", | ||
| 262 | m2->probed_name ? m2->probed_name : m2->modname, | ||
| 263 | moderror(rc)); | ||
| 264 | break; | ||
| 265 | } | ||
| 241 | } else { | 266 | } else { |
| 242 | m2->flags &= ~MODULE_FLAG_LOADED; | 267 | m2->flags &= ~MODULE_FLAG_LOADED; |
| 243 | } | 268 | } |
| 244 | } | 269 | } |
| 245 | /* do not error out if *deps* fail to unload */ | 270 | /* do not error out if *deps* fail to unload */ |
| 246 | first = 0; | 271 | first = 0; |
| 247 | } else if (!(m2->flags & MODULE_FLAG_LOADED)) { | 272 | continue; |
| 248 | options = m2->options; | ||
| 249 | m2->options = NULL; | ||
| 250 | if (m == m2) | ||
| 251 | options = gather_options_str(options, G.cmdline_mopts); | ||
| 252 | rc = bb_init_module(fn, options); | ||
| 253 | DBG("loaded %s '%s', rc:%d", fn, options, rc); | ||
| 254 | if (rc == 0) | ||
| 255 | m2->flags |= MODULE_FLAG_LOADED; | ||
| 256 | free(options); | ||
| 257 | } else { | ||
| 258 | DBG("%s is already loaded, skipping", fn); | ||
| 259 | } | 273 | } |
| 260 | 274 | ||
| 261 | free(fn); | 275 | if (m2->flags & MODULE_FLAG_LOADED) { |
| 262 | } | 276 | DBG("%s is already loaded, skipping", fn); |
| 277 | continue; | ||
| 278 | } | ||
| 263 | 279 | ||
| 264 | if (rc && !(option_mask32 & INSMOD_OPT_SILENT)) { | 280 | options = m2->options; |
| 265 | bb_error_msg("failed to %sload module %s: %s", | 281 | m2->options = NULL; |
| 266 | (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", | 282 | if (m == m2) |
| 283 | options = gather_options_str(options, G.cmdline_mopts); | ||
| 284 | rc = bb_init_module(fn, options); | ||
| 285 | DBG("loaded %s '%s', rc:%d", fn, options, rc); | ||
| 286 | free(options); | ||
| 287 | if (rc) { | ||
| 288 | bb_error_msg("failed to load module %s (%s): %s", | ||
| 267 | m2->probed_name ? m2->probed_name : m2->modname, | 289 | m2->probed_name ? m2->probed_name : m2->modname, |
| 268 | moderror(rc) | 290 | fn, |
| 269 | ); | 291 | moderror(rc) |
| 292 | ); | ||
| 293 | break; | ||
| 294 | } | ||
| 295 | m2->flags |= MODULE_FLAG_LOADED; | ||
| 270 | } | 296 | } |
| 271 | 297 | ||
| 272 | return rc; | 298 | return rc; |
| @@ -278,7 +304,7 @@ static void load_modules_dep(void) | |||
| 278 | char *colon, *tokens[2]; | 304 | char *colon, *tokens[2]; |
| 279 | parser_t *p; | 305 | parser_t *p; |
| 280 | 306 | ||
| 281 | /* Modprobe does not work at all without modprobe.dep, | 307 | /* Modprobe does not work at all without modules.dep, |
| 282 | * even if the full module name is given. Returning error here | 308 | * even if the full module name is given. Returning error here |
| 283 | * was making us later confuse user with this message: | 309 | * was making us later confuse user with this message: |
| 284 | * "module /full/path/to/existing/file/module.ko not found". | 310 | * "module /full/path/to/existing/file/module.ko not found". |
| @@ -387,35 +413,40 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
| 387 | load_modules_dep(); | 413 | load_modules_dep(); |
| 388 | } | 414 | } |
| 389 | 415 | ||
| 416 | rc = 0; | ||
| 390 | while ((me = llist_pop(&G.probes)) != NULL) { | 417 | while ((me = llist_pop(&G.probes)) != NULL) { |
| 391 | if (me->realnames == NULL) { | 418 | if (me->realnames == NULL) { |
| 419 | DBG("probing by module name"); | ||
| 392 | /* This is not an alias. Literal names are blacklisted | 420 | /* This is not an alias. Literal names are blacklisted |
| 393 | * only if '-b' is given. | 421 | * only if '-b' is given. |
| 394 | */ | 422 | */ |
| 395 | if (!(opt & MODPROBE_OPT_BLACKLIST) | 423 | if (!(opt & MODPROBE_OPT_BLACKLIST) |
| 396 | || !(me->flags & MODULE_FLAG_BLACKLISTED) | 424 | || !(me->flags & MODULE_FLAG_BLACKLISTED) |
| 397 | ) { | 425 | ) { |
| 398 | rc = do_modprobe(me); | 426 | rc |= do_modprobe(me); |
| 399 | //FIXME: what if rc > 0? | ||
| 400 | if (rc < 0 && !(opt & INSMOD_OPT_SILENT)) | ||
| 401 | bb_error_msg("module %s not found", | ||
| 402 | me->probed_name); | ||
| 403 | } | 427 | } |
| 404 | } else { | 428 | continue; |
| 405 | /* Probe all realnames */ | ||
| 406 | do { | ||
| 407 | char *realname = llist_pop(&me->realnames); | ||
| 408 | struct module_entry *m2; | ||
| 409 | |||
| 410 | DBG("probing %s by realname %s", me->modname, realname); | ||
| 411 | m2 = get_or_add_modentry(realname); | ||
| 412 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED)) | ||
| 413 | do_modprobe(m2); | ||
| 414 | //FIXME: error check? | ||
| 415 | free(realname); | ||
| 416 | } while (me->realnames != NULL); | ||
| 417 | } | 429 | } |
| 430 | |||
| 431 | /* Probe all real names for the alias */ | ||
| 432 | do { | ||
| 433 | char *realname = llist_pop(&me->realnames); | ||
| 434 | struct module_entry *m2; | ||
| 435 | |||
| 436 | DBG("probing alias %s by realname %s", me->modname, realname); | ||
| 437 | m2 = get_or_add_modentry(realname); | ||
| 438 | if (!(m2->flags & MODULE_FLAG_BLACKLISTED) | ||
| 439 | && (!(m2->flags & MODULE_FLAG_LOADED) | ||
| 440 | || (opt & MODPROBE_OPT_REMOVE)) | ||
| 441 | ) { | ||
| 442 | //TODO: we can pass "me" as 2nd param to do_modprobe, | ||
| 443 | //and make do_modprobe emit more meaningful error messages | ||
| 444 | //with alias name included, not just module name alias resolves to. | ||
| 445 | rc |= do_modprobe(m2); | ||
| 446 | } | ||
| 447 | free(realname); | ||
| 448 | } while (me->realnames != NULL); | ||
| 418 | } | 449 | } |
| 419 | 450 | ||
| 420 | return EXIT_SUCCESS; | 451 | return (rc != 0); |
| 421 | } | 452 | } |
diff --git a/modutils/modutils.c b/modutils/modutils.c index f437a9829..969926db9 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c | |||
| @@ -25,7 +25,7 @@ void FAST_FUNC replace(char *s, char what, char with) | |||
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | char * FAST_FUNC replace_underscores(char *s) | 28 | char* FAST_FUNC replace_underscores(char *s) |
| 29 | { | 29 | { |
| 30 | replace(s, '-', '_'); | 30 | replace(s, '-', '_'); |
| 31 | return s; | 31 | return s; |
| @@ -45,7 +45,7 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) | |||
| 45 | return len; | 45 | return len; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | char * FAST_FUNC filename2modname(const char *filename, char *modname) | 48 | char* FAST_FUNC filename2modname(const char *filename, char *modname) |
| 49 | { | 49 | { |
| 50 | int i; | 50 | int i; |
| 51 | char *from; | 51 | char *from; |
| @@ -62,24 +62,6 @@ char * FAST_FUNC filename2modname(const char *filename, char *modname) | |||
| 62 | return modname; | 62 | return modname; |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | const char * FAST_FUNC moderror(int err) | ||
| 66 | { | ||
| 67 | switch (err) { | ||
| 68 | case -1: | ||
| 69 | return "no such module"; | ||
| 70 | case ENOEXEC: | ||
| 71 | return "invalid module format"; | ||
| 72 | case ENOENT: | ||
| 73 | return "unknown symbol in module, or unknown parameter"; | ||
| 74 | case ESRCH: | ||
| 75 | return "module has wrong symbol version"; | ||
| 76 | case ENOSYS: | ||
| 77 | return "kernel does not support requested operation"; | ||
| 78 | default: | ||
| 79 | return strerror(err); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | char * FAST_FUNC parse_cmdline_module_options(char **argv) | 65 | char * FAST_FUNC parse_cmdline_module_options(char **argv) |
| 84 | { | 66 | { |
| 85 | char *options; | 67 | char *options; |
| @@ -95,6 +77,11 @@ char * FAST_FUNC parse_cmdline_module_options(char **argv) | |||
| 95 | return options; | 77 | return options; |
| 96 | } | 78 | } |
| 97 | 79 | ||
| 80 | /* Return: | ||
| 81 | * 0 on success, | ||
| 82 | * -errno on open/read error, | ||
| 83 | * errno on init_module() error | ||
| 84 | */ | ||
| 98 | int FAST_FUNC bb_init_module(const char *filename, const char *options) | 85 | int FAST_FUNC bb_init_module(const char *filename, const char *options) |
| 99 | { | 86 | { |
| 100 | size_t len; | 87 | size_t len; |
| @@ -104,6 +91,7 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options) | |||
| 104 | if (!options) | 91 | if (!options) |
| 105 | options = ""; | 92 | options = ""; |
| 106 | 93 | ||
| 94 | //TODO: audit bb_init_module_24 to match error code convention | ||
| 107 | #if ENABLE_FEATURE_2_4_MODULES | 95 | #if ENABLE_FEATURE_2_4_MODULES |
| 108 | if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) | 96 | if (get_linux_version_code() < KERNEL_VERSION(2,6,0)) |
| 109 | return bb_init_module_24(filename, options); | 97 | return bb_init_module_24(filename, options); |
| @@ -111,19 +99,40 @@ int FAST_FUNC bb_init_module(const char *filename, const char *options) | |||
| 111 | 99 | ||
| 112 | /* Use the 2.6 way */ | 100 | /* Use the 2.6 way */ |
| 113 | len = INT_MAX - 4095; | 101 | len = INT_MAX - 4095; |
| 114 | rc = ENOENT; | 102 | errno = ENOMEM; /* may be changed by e.g. open errors below */ |
| 115 | image = xmalloc_open_zipped_read_close(filename, &len); | 103 | image = xmalloc_open_zipped_read_close(filename, &len); |
| 116 | if (image) { | 104 | if (!image) |
| 117 | rc = 0; | 105 | return -errno; |
| 118 | if (init_module(image, len, options) != 0) | ||
| 119 | rc = errno; | ||
| 120 | free(image); | ||
| 121 | } | ||
| 122 | 106 | ||
| 107 | errno = 0; | ||
| 108 | init_module(image, len, options); | ||
| 109 | rc = errno; | ||
| 110 | free(image); | ||
| 123 | return rc; | 111 | return rc; |
| 124 | } | 112 | } |
| 125 | 113 | ||
| 126 | int FAST_FUNC bb_delete_module(const char *module, unsigned int flags) | 114 | int FAST_FUNC bb_delete_module(const char *module, unsigned int flags) |
| 127 | { | 115 | { |
| 128 | return delete_module(module, flags); | 116 | errno = 0; |
| 117 | delete_module(module, flags); | ||
| 118 | return errno; | ||
| 119 | } | ||
| 120 | |||
| 121 | const char* FAST_FUNC moderror(int err) | ||
| 122 | { | ||
| 123 | switch (err) { | ||
| 124 | case -1: /* btw: it's -EPERM */ | ||
| 125 | return "no such module"; | ||
| 126 | case ENOEXEC: | ||
| 127 | return "invalid module format"; | ||
| 128 | case ENOENT: | ||
| 129 | return "unknown symbol in module, or unknown parameter"; | ||
| 130 | case ESRCH: | ||
| 131 | return "module has wrong symbol version"; | ||
| 132 | case ENOSYS: | ||
| 133 | return "kernel does not support requested operation"; | ||
| 134 | } | ||
| 135 | if (err < 0) /* should always be */ | ||
| 136 | err = -err; | ||
| 137 | return strerror(err); | ||
| 129 | } | 138 | } |
diff --git a/modutils/modutils.h b/modutils/modutils.h index 8cca5ccfe..1cf4bba95 100644 --- a/modutils/modutils.h +++ b/modutils/modutils.h | |||
| @@ -17,7 +17,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN | |||
| 17 | * internally for the maximum alias name length, which can be quite long */ | 17 | * internally for the maximum alias name length, which can be quite long */ |
| 18 | #define MODULE_NAME_LEN 256 | 18 | #define MODULE_NAME_LEN 256 |
| 19 | 19 | ||
| 20 | const char *moderror(int err) FAST_FUNC; | ||
| 21 | void replace(char *s, char what, char with) FAST_FUNC; | 20 | void replace(char *s, char what, char with) FAST_FUNC; |
| 22 | char *replace_underscores(char *s) FAST_FUNC; | 21 | char *replace_underscores(char *s) FAST_FUNC; |
| 23 | int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; | 22 | int string_to_llist(char *string, llist_t **llist, const char *delim) FAST_FUNC; |
| @@ -52,8 +51,19 @@ enum { | |||
| 52 | #endif | 51 | #endif |
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 54 | /* Return: | ||
| 55 | * 0 on success, | ||
| 56 | * -errno on open/read error, | ||
| 57 | * errno on init_module() error | ||
| 58 | */ | ||
| 55 | int FAST_FUNC bb_init_module(const char *module, const char *options); | 59 | int FAST_FUNC bb_init_module(const char *module, const char *options); |
| 60 | /* Return: | ||
| 61 | * 0 on success, | ||
| 62 | * errno on init_module() error | ||
| 63 | */ | ||
| 56 | int FAST_FUNC bb_delete_module(const char *module, unsigned int flags); | 64 | int FAST_FUNC bb_delete_module(const char *module, unsigned int flags); |
| 65 | /* Translates error return to a string */ | ||
| 66 | const char *moderror(int err) FAST_FUNC; | ||
| 57 | 67 | ||
| 58 | #if ENABLE_FEATURE_2_4_MODULES | 68 | #if ENABLE_FEATURE_2_4_MODULES |
| 59 | int FAST_FUNC bb_init_module_24(const char *module, const char *options); | 69 | int FAST_FUNC bb_init_module_24(const char *module, const char *options); |
