Currently, depmod and modprobe can only use directories of the form ROOT/lib/modules/VERSION, where ROOT and VERSION can be specified on the command line. Additionally, when used with explicitly-listed modules depmod requires absolute paths, making it difficult to generate a nonstandard module layout without symlink hacks and absolute paths. This lifts both restrictions with a new --moddir option. --moddir specifies an exact directory name and, when --moddir is used, depmod will accept relative module paths on the command line. Signed-off-by: Andy Lutomirski <luto@xxxxxxxxxxxxxx> --- man/depmod.xml | 29 +++++++++++++++++++++++++++++ man/modprobe.xml | 18 ++++++++++++++++++ tools/depmod.c | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ tools/modprobe.c | 16 ++++++++++++++++ 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/man/depmod.xml b/man/depmod.xml index a9b61d9..1a8c10e 100644 --- a/man/depmod.xml +++ b/man/depmod.xml @@ -65,6 +65,7 @@ <arg><option>-n</option></arg> <arg><option>-v</option></arg> <arg><option>-P <replaceable>prefix</replaceable></option></arg> + <arg><option>--moddir <replaceable>moddir</replaceable></option></arg> <arg><option>-w</option></arg> <arg><option><replaceable>version</replaceable></option></arg> <arg rep='repeat'><option><replaceable>filename</replaceable></option></arg> @@ -148,6 +149,34 @@ option if you are a distribution vendor who needs to pre-generate the meta-data files rather than running depmod again later. </para> + <para> + The <command>--moddir</command> option can be used instead. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> + <option>--moddir <replaceable>moddir</replaceable></option> + </term> + <listitem> + <para> + If your modules are not currently in the (normal) directory + <filename>/lib/modules/</filename><replaceable>version</replaceable>, + but in a staging area, you can specify a + <replaceable>moddir</replaceable> to override the directory + in which <command>depmod</command> writes its output and + possibly searches for modules. + </para> + <para> + If <command>--moddir</command> is specified, then module + file names listed on the command line are permitted to use + relative paths; relative paths will be interpreted relative + to <replaceable>moddir</replaceable>. + </para> + <para> + This option cannot be used with <command>-b</command> or + with an explicit kernel version. + </para> </listitem> </varlistentry> <varlistentry> diff --git a/man/modprobe.xml b/man/modprobe.xml index 4c6c832..735acf1 100644 --- a/man/modprobe.xml +++ b/man/modprobe.xml @@ -407,6 +407,24 @@ </varlistentry> <varlistentry> <term> + <option>--moddir <replaceable>moddir</replaceable></option> + </term> + <listitem> + <para> + If your modules are not currently in the (normal) directory + <filename>/lib/modules/</filename><replaceable>version</replaceable>, + but in a staging area, you can specify a + <replaceable>moddir</replaceable> to override the directory + in which <command>modprobe</command> searches. + </para> + <para> + This option cannot be used with <command>--set-version</command> or + <command>--dirname</command>. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term> <option>--show-depends</option> </term> <listitem> diff --git a/tools/depmod.c b/tools/depmod.c index b1b5874..5cba93b 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -48,6 +48,9 @@ static const char *default_cfg_paths[] = { NULL }; +enum LONGOPTS { + MODDIR_OPT = 1000, +}; static const char cmdopts_s[] = "aAb:C:E:F:euqrvnP:wmVh"; static const struct option cmdopts[] = { { "all", no_argument, 0, 'a' }, @@ -66,6 +69,7 @@ static const struct option cmdopts[] = { { "symbol-prefix", required_argument, 0, 'P' }, { "warn", no_argument, 0, 'w' }, { "map", no_argument, 0, 'm' }, /* deprecated */ + { "moddir", required_argument, 0, MODDIR_OPT }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { } @@ -94,6 +98,8 @@ static void help(void) "\n" "The following options are useful for people managing distributions:\n" "\t-b, --basedir=DIR Use an image of a module tree.\n" + "\t--moddir=MODDIR Specify a target directory and allow relative\n" + "\t paths. Do not use -b or specify a version.\n" "\t-F, --filesyms=FILE Use the file instead of the\n" "\t current kernel symbols.\n" "\t-E, --symvers=FILE Use Module.symvers file to check\n" @@ -1045,7 +1051,8 @@ static void depmod_shutdown(struct depmod *depmod) kmod_unref(depmod->ctx); } -static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod) +static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod, + const char *relpath) { const struct cfg *cfg = depmod->cfg; const char *modname, *lastslash; @@ -1070,11 +1077,14 @@ static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod) mod->path = strdup(kmod_module_get_path(kmod)); lastslash = strrchr(mod->path, '/'); mod->baselen = lastslash - mod->path; - if (strncmp(mod->path, cfg->dirname, cfg->dirnamelen) == 0 && - mod->path[cfg->dirnamelen] == '/') + if (relpath) { + mod->relpath = strdup(relpath); + } else if (strncmp(mod->path, cfg->dirname, cfg->dirnamelen) == 0 && + mod->path[cfg->dirnamelen] == '/') { mod->relpath = mod->path + cfg->dirnamelen + 1; - else + } else { mod->relpath = NULL; + } err = hash_add_unique(depmod->modules_by_name, mod->modname, mod); if (err < 0) { @@ -1082,7 +1092,7 @@ static int depmod_module_add(struct depmod *depmod, struct kmod_module *kmod) goto fail; } - if (mod->relpath != NULL) { + if (mod->relpath != NULL && !relpath) { size_t uncrelpathlen = lastslash - mod->relpath + modnamelen + kmod_exts[KMOD_EXT_UNC].len; mod->uncrelpath = memdup(mod->relpath, uncrelpathlen + 1); @@ -1221,7 +1231,7 @@ add: return err; } - err = depmod_module_add(depmod, kmod); + err = depmod_module_add(depmod, kmod, NULL); if (err < 0) { ERR("could not add module %s: %s\n", path, strerror(-err)); @@ -2467,6 +2477,7 @@ static int do_depmod(int argc, char *argv[]) const char *system_map = NULL; const char *module_symvers = NULL; const char *null_kmod_config = NULL; + const char *moddir = NULL; struct utsname un; struct kmod_ctx *ctx = NULL; struct cfg cfg; @@ -2540,6 +2551,9 @@ static int do_depmod(int argc, char *argv[]) WRN("Ignored deprecated option -%c\n", c); break; + case MODDIR_OPT: + moddir = optarg; + break; case 'h': help(); free(config_paths); @@ -2556,7 +2570,14 @@ static int do_depmod(int argc, char *argv[]) } } - if (optind < argc && is_version_number(argv[optind])) { + if (moddir && root) { + ERR("--moddir and -b cannot be used together.\n"); + goto cmdline_failed; + } + + if (moddir) { + cfg.kversion = NULL; + } else if (optind < argc && is_version_number(argv[optind])) { cfg.kversion = argv[optind]; optind++; } else { @@ -2567,9 +2588,20 @@ static int do_depmod(int argc, char *argv[]) cfg.kversion = un.release; } - cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX, - "%s/lib/modules/%s", - root == NULL ? "" : root, cfg.kversion); + if (moddir) { + if (chdir(moddir) != 0) { + CRIT("chdir(%s): %s\n", moddir, strerror(errno)); + goto cmdline_failed; + } + + strcpy(cfg.dirname, "."); + cfg.dirnamelen = 1; + } else { + cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX, + "%s/lib/modules/%s", + root == NULL ? "" : root, + cfg.kversion); + } if (optind == argc) all = 1; @@ -2638,7 +2670,7 @@ static int do_depmod(int argc, char *argv[]) const char *path = argv[i]; struct kmod_module *mod; - if (path[0] != '/') { + if (path[0] != '/' && !moddir) { CRIT("%s: not absolute path.\n", path); goto cmdline_modules_failed; } @@ -2650,7 +2682,7 @@ static int do_depmod(int argc, char *argv[]) goto cmdline_modules_failed; } - err = depmod_module_add(&depmod, mod); + err = depmod_module_add(&depmod, mod, path); if (err < 0) { CRIT("could not add module %s: %s\n", path, strerror(-err)); diff --git a/tools/modprobe.c b/tools/modprobe.c index 6b34658..b6d8693 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -56,6 +56,9 @@ static int strip_vermagic = 0; static int remove_dependencies = 0; static int quiet_inuse = 0; +enum LONGOPTS { + MODDIR_OPT = 1000, +}; static const char cmdopts_s[] = "arRibfDcnC:d:S:sqvVh"; static const struct option cmdopts[] = { {"all", no_argument, 0, 'a'}, @@ -82,6 +85,7 @@ static const struct option cmdopts[] = { {"config", required_argument, 0, 'C'}, {"dirname", required_argument, 0, 'd'}, {"set-version", required_argument, 0, 'S'}, + {"moddir", required_argument, 0, MODDIR_OPT}, {"syslog", no_argument, 0, 's'}, {"quiet", no_argument, 0, 'q'}, @@ -131,6 +135,8 @@ static void help(void) "\t-C, --config=FILE Use FILE instead of default search paths\n" "\t-d, --dirname=DIR Use DIR as filesystem root for /lib/modules\n" "\t-S, --set-version=VERSION Use VERSION instead of `uname -r`\n" + "\t--moddir=MODDIR Specify a target directory and allow\n" + "\t relative paths. Do not use with -d or -s.\n" "\t-s, --syslog print to syslog, not stderr\n" "\t-q, --quiet disable messages\n" @@ -749,6 +755,7 @@ static int do_modprobe(int argc, char **orig_argv) const char *dirname = NULL; const char *root = NULL; const char *kversion = NULL; + const char *moddir = NULL; int use_all = 0; int do_remove = 0; int do_show_config = 0; @@ -835,6 +842,9 @@ static int do_modprobe(int argc, char **orig_argv) case 'S': kversion = optarg; break; + case MODDIR_OPT: + moddir = optarg; + break; case 's': env_modprobe_options_append("-s"); use_syslog = 1; @@ -878,8 +888,14 @@ static int do_modprobe(int argc, char **orig_argv) } } + if (moddir != NULL) + dirname = moddir; if (root != NULL || kversion != NULL) { struct utsname u; + if (moddir != NULL) { + ERR("--moddir cannot be used with -d or -S.\n"); + goto done; + } if (root == NULL) root = ""; if (kversion == NULL) { -- 1.8.5.3 -- To unsubscribe from this list: send the line "unsubscribe linux-modules" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html