date: accept 'yyyy-mm-dd HH' and 'yyyy-mm-dd' date formats
[oweals/busybox.git] / modutils / modprobe-small.c
index 05f2c34eb6fbe9888cbf4a239dc85e7203b3ef2a..5b78363445dd651452b53fb8eb786d882a0b36d7 100644 (file)
@@ -8,6 +8,12 @@
  * Licensed under GPLv2, see file LICENSE in this source tree.
  */
 
+//applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
+//applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe))
+
 #include "libbb.h"
 /* After libbb.h, since it needs sys/types.h on some systems */
 #include <sys/utsname.h> /* uname() */
@@ -18,10 +24,13 @@ extern int delete_module(const char *module, unsigned flags);
 extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
 
 
-#define dbg1_error_msg(...) ((void)0)
-#define dbg2_error_msg(...) ((void)0)
-//#define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__)
-//#define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__)
+#if 1
+# define dbg1_error_msg(...) ((void)0)
+# define dbg2_error_msg(...) ((void)0)
+#else
+# define dbg1_error_msg(...) bb_error_msg(__VA_ARGS__)
+# define dbg2_error_msg(...) bb_error_msg(__VA_ARGS__)
+#endif
 
 #define DEPFILE_BB CONFIG_DEFAULT_DEPMOD_FILE".bb"
 
@@ -196,6 +205,7 @@ static void parse_module(module_info *info, const char *pathname)
        /* Read (possibly compressed) module */
        len = 64 * 1024 * 1024; /* 64 Mb at most */
        module_image = xmalloc_open_zipped_read_close(pathname, &len);
+       /* module_image == NULL is ok here, find_keyword handles it */
 //TODO: optimize redundant module body reads
 
        /* "alias1 symbol:sym1 alias2 symbol:sym2" */
@@ -579,24 +589,30 @@ static void process_module(char *name, const char *cmdline_options)
 
        /* rmmod? unload it by name */
        if (is_rmmod) {
-               if (delete_module(name, O_NONBLOCK | O_EXCL) != 0
-                && !(option_mask32 & OPT_q)
-               ) {
-                       bb_perror_msg("remove '%s'", name);
+               if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) {
+                       if (!(option_mask32 & OPT_q))
+                               bb_perror_msg("remove '%s'", name);
                        goto ret;
                }
-               /* N.B. we do not stop here -
+
+               if (applet_name[0] == 'r') {
+                       /* rmmod: do not remove dependencies, exit */
+                       goto ret;
+               }
+
+               /* modprobe -r: we do not stop here -
                 * continue to unload modules on which the module depends:
                 * "-r --remove: option causes modprobe to remove a module.
                 * If the modules it depends on are also unused, modprobe
-                * will try to remove them, too." */
+                * will try to remove them, too."
+                */
        }
 
        if (!info) {
                /* both dirscan and find_alias found nothing */
-               if (applet_name[0] != 'd') /* it wasn't depmod */
+               if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */
                        bb_error_msg("module '%s' not found", name);
-//TODO: _and_die()?
+//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline?
                goto ret;
        }
 
@@ -686,17 +702,59 @@ The following options are useful for people managing distributions:
 */
 
 //usage:#if ENABLE_MODPROBE_SMALL
+
+//// Note: currently, help system shows modprobe --help text for all aliased cmds
+//// (see APPLET_ODDNAME macro definition).
+//// All other help texts defined below are not used. FIXME?
+
+//usage:#define depmod_trivial_usage NOUSAGE_STR
+//usage:#define depmod_full_usage ""
+
+//usage:#define lsmod_trivial_usage
+//usage:       ""
+//usage:#define lsmod_full_usage "\n\n"
+//usage:       "List the currently loaded kernel modules"
+
+//usage:#define insmod_trivial_usage
+//usage:       IF_FEATURE_2_4_MODULES("[OPTIONS] MODULE ")
+//usage:       IF_NOT_FEATURE_2_4_MODULES("FILE ")
+//usage:       "[SYMBOL=VALUE]..."
+//usage:#define insmod_full_usage "\n\n"
+//usage:       "Load the specified kernel modules into the kernel"
+//usage:       IF_FEATURE_2_4_MODULES( "\n"
+//usage:     "\n       -f      Force module to load into the wrong kernel version"
+//usage:     "\n       -k      Make module autoclean-able"
+//usage:     "\n       -v      Verbose"
+//usage:     "\n       -q      Quiet"
+//usage:     "\n       -L      Lock: prevent simultaneous loads"
+//usage:       IF_FEATURE_INSMOD_LOAD_MAP(
+//usage:     "\n       -m      Output load map to stdout"
+//usage:       )
+//usage:     "\n       -x      Don't export externs"
+//usage:       )
+
+//usage:#define rmmod_trivial_usage
+//usage:       "[-wfa] [MODULE]..."
+//usage:#define rmmod_full_usage "\n\n"
+//usage:       "Unload kernel modules\n"
+//usage:     "\n       -w      Wait until the module is no longer used"
+//usage:     "\n       -f      Force unload"
+//usage:     "\n       -a      Remove all unused modules (recursively)"
+//usage:
+//usage:#define rmmod_example_usage
+//usage:       "$ rmmod tulip\n"
+
 //usage:#define modprobe_trivial_usage
 //usage:       "[-qfwrsv] MODULE [symbol=value]..."
 //usage:#define modprobe_full_usage "\n\n"
-//usage:       "Options:"
-//usage:     "\n       -r      Remove MODULE (stacks) or do autoclean"
+//usage:       "       -r      Remove MODULE (stacks) or do autoclean"
 //usage:     "\n       -q      Quiet"
 //usage:     "\n       -v      Verbose"
 //usage:     "\n       -f      Force"
 //usage:     "\n       -w      Wait for unload"
 //usage:     "\n       -s      Report via syslog instead of stderr"
-//usage:#endif /* ENABLE_MODPROBE_SMALL */
+
+//usage:#endif
 
 int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int modprobe_main(int argc UNUSED_PARAM, char **argv)
@@ -758,7 +816,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
        opt_complementary = "-1";
        /* only -q (quiet) and -r (rmmod),
         * the rest are accepted and ignored (compat) */
-       getopt32(argv, "qrfsvw");
+       getopt32(argv, "qrfsvwb");
        argv += optind;
 
        /* are we rmmod? -> simulate modprobe -r */
@@ -795,13 +853,17 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
                void *map;
 
                len = MAXINT(ssize_t);
-               map = xmalloc_xopen_read_close(*argv, &len);
+               map = xmalloc_open_zipped_read_close(*argv, &len);
+               if (!map)
+                       bb_perror_msg_and_die("can't read '%s'", *argv);
                if (init_module(map, len,
                        IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(options ? options : "")
                        IF_NOT_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE("")
-                               ) != 0)
+                       ) != 0
+               ) {
                        bb_error_msg_and_die("can't insert '%s': %s",
                                        *argv, moderror(errno));
+               }
                return 0;
        }
 
@@ -811,8 +873,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
        /* Load/remove modules.
         * Only rmmod loops here, modprobe has only argv[0] */
        do {
-               process_module(*argv++, options);
-       } while (*argv);
+               process_module(*argv, options);
+       } while (*++argv);
 
        if (ENABLE_FEATURE_CLEAN_UP) {
                IF_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE(free(options);)