toolbox: add modprobe
Add an implementation of modprobe based on libmodprobe. Change-Id: I85ba440766406fe6ca7e90bec204d06632785a66
This commit is contained in:
parent
ded44c06be
commit
64a553451a
3 changed files with 208 additions and 1 deletions
|
@ -24,6 +24,7 @@ cc_defaults {
|
|||
"toolbox.c",
|
||||
"getevent.c",
|
||||
"getprop.cpp",
|
||||
"modprobe.cpp",
|
||||
"setprop.cpp",
|
||||
"start.cpp",
|
||||
],
|
||||
|
@ -33,11 +34,15 @@ cc_defaults {
|
|||
shared_libs: [
|
||||
"libbase",
|
||||
],
|
||||
static_libs: ["libpropertyinfoparser"],
|
||||
static_libs: [
|
||||
"libmodprobe",
|
||||
"libpropertyinfoparser",
|
||||
],
|
||||
|
||||
symlinks: [
|
||||
"getevent",
|
||||
"getprop",
|
||||
"modprobe",
|
||||
"setprop",
|
||||
"start",
|
||||
"stop",
|
||||
|
|
201
toolbox/modprobe.cpp
Normal file
201
toolbox/modprobe.cpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <android-base/strings.h>
|
||||
#include <modprobe/modprobe.h>
|
||||
|
||||
enum modprobe_mode {
|
||||
AddModulesMode,
|
||||
RemoveModulesMode,
|
||||
ListModulesMode,
|
||||
ShowDependenciesMode,
|
||||
};
|
||||
|
||||
static void print_usage(void) {
|
||||
std::cerr << "Usage:" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << " modprobe [-alrqvsDb] [-d DIR] [MODULE]+" << std::endl;
|
||||
std::cerr << " modprobe [-alrqvsDb] [-d DIR] MODULE [symbol=value][...]" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Options:" << std::endl;
|
||||
std::cerr << " -b: Apply blacklist to module names too" << std::endl;
|
||||
std::cerr << " -d: Load modules from DIR, option may be used multiple times" << std::endl;
|
||||
std::cerr << " -D: Print dependencies for modules only, do not load";
|
||||
std::cerr << " -h: Print this help" << std::endl;
|
||||
std::cerr << " -l: List modules matching pattern" << std::endl;
|
||||
std::cerr << " -r: Remove MODULE (multiple modules may be specified)" << std::endl;
|
||||
std::cerr << " -q: Quiet" << std::endl;
|
||||
std::cerr << " -v: Verbose" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
#define check_mode() \
|
||||
if (mode != AddModulesMode) { \
|
||||
std::cerr << "Error, multiple mode flags specified" << std::endl; \
|
||||
print_usage(); \
|
||||
return EXIT_FAILURE; \
|
||||
}
|
||||
|
||||
extern "C" int modprobe_main(int argc, char** argv) {
|
||||
std::vector<std::string> modules;
|
||||
std::string module_parameters;
|
||||
std::vector<std::string> mod_dirs;
|
||||
modprobe_mode mode = AddModulesMode;
|
||||
bool blacklist = false;
|
||||
bool verbose = false;
|
||||
int rv = EXIT_SUCCESS;
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "abd:Dhlqrv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'a':
|
||||
// toybox modprobe supported -a to load multiple modules, this
|
||||
// is supported here by default, ignore flag
|
||||
check_mode();
|
||||
break;
|
||||
case 'b':
|
||||
blacklist = true;
|
||||
break;
|
||||
case 'd':
|
||||
mod_dirs.emplace_back(optarg);
|
||||
break;
|
||||
case 'D':
|
||||
check_mode();
|
||||
mode = ShowDependenciesMode;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return EXIT_SUCCESS;
|
||||
case 'l':
|
||||
check_mode();
|
||||
mode = ListModulesMode;
|
||||
break;
|
||||
case 'q':
|
||||
verbose = false;
|
||||
break;
|
||||
case 'r':
|
||||
check_mode();
|
||||
mode = RemoveModulesMode;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unrecognized option: " << opt << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int parameter_count = 0;
|
||||
for (opt = optind; opt < argc; opt++) {
|
||||
if (!strchr(argv[opt], '=')) {
|
||||
modules.emplace_back(argv[opt]);
|
||||
} else {
|
||||
parameter_count++;
|
||||
if (module_parameters.empty()) {
|
||||
module_parameters = argv[opt];
|
||||
} else {
|
||||
module_parameters = module_parameters + " " + argv[opt];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
std::cout << "mode is " << mode << std::endl;
|
||||
std::cout << "verbose is " << verbose << std::endl;
|
||||
std::cout << "mod_dirs is: " << android::base::Join(mod_dirs, "") << std::endl;
|
||||
std::cout << "modules is: " << android::base::Join(modules, "") << std::endl;
|
||||
std::cout << "module parameters is: " << android::base::Join(module_parameters, "")
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (modules.empty()) {
|
||||
if (mode == ListModulesMode) {
|
||||
// emulate toybox modprobe list with no pattern (list all)
|
||||
modules.emplace_back("*");
|
||||
} else {
|
||||
std::cerr << "No modules given." << std::endl;
|
||||
print_usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (mod_dirs.empty()) {
|
||||
std::cerr << "No module configuration directories given." << std::endl;
|
||||
print_usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (parameter_count && modules.size() > 1) {
|
||||
std::cerr << "Only one module may be loaded when specifying module parameters."
|
||||
<< std::endl;
|
||||
print_usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Modprobe m(mod_dirs);
|
||||
m.EnableVerbose(verbose);
|
||||
if (blacklist) {
|
||||
m.EnableBlacklist(true);
|
||||
}
|
||||
|
||||
for (const auto& module : modules) {
|
||||
switch (mode) {
|
||||
case AddModulesMode:
|
||||
if (!m.LoadWithAliases(module, true, module_parameters)) {
|
||||
std::cerr << "Failed to load module " << module;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case RemoveModulesMode:
|
||||
if (!m.Remove(module)) {
|
||||
std::cerr << "Failed to remove module " << module;
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case ListModulesMode: {
|
||||
std::vector<std::string> list = m.ListModules(module);
|
||||
std::cout << android::base::Join(list, "\n") << std::endl;
|
||||
break;
|
||||
}
|
||||
case ShowDependenciesMode: {
|
||||
std::vector<std::string> pre_deps;
|
||||
std::vector<std::string> deps;
|
||||
std::vector<std::string> post_deps;
|
||||
if (!m.GetAllDependencies(module, &pre_deps, &deps, &post_deps)) {
|
||||
rv = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
std::cout << "Dependencies for " << module << ":" << std::endl;
|
||||
std::cout << "Soft pre-dependencies:" << std::endl;
|
||||
std::cout << android::base::Join(pre_deps, "\n") << std::endl;
|
||||
std::cout << "Hard dependencies:" << std::endl;
|
||||
std::cout << android::base::Join(deps, "\n") << std::endl;
|
||||
std::cout << "Soft post-dependencies:" << std::endl;
|
||||
std::cout << android::base::Join(post_deps, "\n") << std::endl;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
std::cerr << "Bad mode";
|
||||
rv = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
TOOL(getevent)
|
||||
TOOL(getprop)
|
||||
TOOL(modprobe)
|
||||
TOOL(setprop)
|
||||
TOOL(start)
|
||||
TOOL(stop)
|
||||
|
|
Loading…
Reference in a new issue