modprobe: add -s/--syslog flag
There is a desire to ensure that modprobe as a service can log to kmesg to help triage issues, so add support for the -s or --syslog flag to do so. SideEffects: - help goes to stdout instead of stderr. - verbose flag once, sets DEBUG, twice, sets VERBOSE minimum. - quiet flag sets WARNING minimum. Bug: 159424228 Bug: 151950334 Test: use modprobe as a service to load modules, check logs Change-Id: I884995f364b0fc604861797eb90d7225a372f864
This commit is contained in:
parent
3d246cced8
commit
63368beaba
|
@ -15,15 +15,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <modprobe/modprobe.h>
|
#include <modprobe/modprobe.h>
|
||||||
|
|
||||||
|
@ -37,32 +35,31 @@ enum modprobe_mode {
|
||||||
};
|
};
|
||||||
|
|
||||||
void print_usage(void) {
|
void print_usage(void) {
|
||||||
std::cerr << "Usage:" << std::endl;
|
LOG(INFO) << "Usage:";
|
||||||
std::cerr << std::endl;
|
LOG(INFO);
|
||||||
// -d option is required on Android
|
// -d option is required on Android
|
||||||
std::cerr << " modprobe [options] -d DIR [--all=FILE|MODULE]..." << std::endl;
|
LOG(INFO) << " modprobe [options] -d DIR [--all=FILE|MODULE]...";
|
||||||
std::cerr << " modprobe [options] -d DIR MODULE [symbol=value]..." << std::endl;
|
LOG(INFO) << " modprobe [options] -d DIR MODULE [symbol=value]...";
|
||||||
std::cerr << std::endl;
|
LOG(INFO);
|
||||||
std::cerr << "Options:" << std::endl;
|
LOG(INFO) << "Options:";
|
||||||
std::cerr << " --all=FILE: FILE to acquire module names from" << std::endl;
|
LOG(INFO) << " --all=FILE: FILE to acquire module names from";
|
||||||
std::cerr << " -b, --use-blocklist: Apply blocklist to module names too" << std::endl;
|
LOG(INFO) << " -b, --use-blocklist: Apply blocklist to module names too";
|
||||||
std::cerr << " -d, --dirname=DIR: Load modules from DIR, option may be used multiple times"
|
LOG(INFO) << " -d, --dirname=DIR: Load modules from DIR, option may be used multiple times";
|
||||||
<< std::endl;
|
LOG(INFO) << " -D, --show-depends: Print dependencies for modules only, do not load";
|
||||||
std::cerr << " -D, --show-depends: Print dependencies for modules only, do not load"
|
LOG(INFO) << " -h, --help: Print this help";
|
||||||
<< std::endl;
|
LOG(INFO) << " -l, --list: List modules matching pattern";
|
||||||
std::cerr << " -h, --help: Print this help" << std::endl;
|
LOG(INFO) << " -r, --remove: Remove MODULE (multiple modules may be specified)";
|
||||||
std::cerr << " -l, --list: List modules matching pattern" << std::endl;
|
LOG(INFO) << " -s, --syslog: print to syslog also";
|
||||||
std::cerr << " -r, --remove: Remove MODULE (multiple modules may be specified)" << std::endl;
|
LOG(INFO) << " -q, --quiet: disable messages";
|
||||||
std::cerr << " -q, --quiet: disable messages" << std::endl;
|
LOG(INFO) << " -v, --verbose: enable more messages, even more with a second -v";
|
||||||
std::cerr << " -v, --verbose: enable more messages" << std::endl;
|
LOG(INFO);
|
||||||
std::cerr << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define check_mode() \
|
#define check_mode() \
|
||||||
if (mode != AddModulesMode) { \
|
if (mode != AddModulesMode) { \
|
||||||
std::cerr << "Error, multiple mode flags specified" << std::endl; \
|
LOG(ERROR) << "multiple mode flags specified"; \
|
||||||
print_usage(); \
|
print_usage(); \
|
||||||
return EXIT_FAILURE; \
|
return EXIT_FAILURE; \
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string stripComments(const std::string& str) {
|
std::string stripComments(const std::string& str) {
|
||||||
|
@ -76,16 +73,28 @@ std::string stripComments(const std::string& str) {
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto syslog = false;
|
||||||
|
|
||||||
|
void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
|
||||||
|
const char* file, unsigned int line, const char* message) {
|
||||||
|
android::base::StdioLogger(id, severity, tag, file, line, message);
|
||||||
|
if (syslog && message[0]) {
|
||||||
|
android::base::KernelLogger(id, severity, tag, file, line, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
extern "C" int modprobe_main(int argc, char** argv) {
|
extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
|
android::base::InitLogging(argv, MyLogger);
|
||||||
|
android::base::SetMinimumLogSeverity(android::base::INFO);
|
||||||
|
|
||||||
std::vector<std::string> modules;
|
std::vector<std::string> modules;
|
||||||
std::string module_parameters;
|
std::string module_parameters;
|
||||||
std::string mods;
|
std::string mods;
|
||||||
std::vector<std::string> mod_dirs;
|
std::vector<std::string> mod_dirs;
|
||||||
modprobe_mode mode = AddModulesMode;
|
modprobe_mode mode = AddModulesMode;
|
||||||
bool blocklist = false;
|
bool blocklist = false;
|
||||||
bool verbose = false;
|
|
||||||
int rv = EXIT_SUCCESS;
|
int rv = EXIT_SUCCESS;
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
|
@ -102,10 +111,11 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
{ "list", no_argument, 0, 'l' },
|
{ "list", no_argument, 0, 'l' },
|
||||||
{ "quiet", no_argument, 0, 'q' },
|
{ "quiet", no_argument, 0, 'q' },
|
||||||
{ "remove", no_argument, 0, 'r' },
|
{ "remove", no_argument, 0, 'r' },
|
||||||
|
{ "syslog", no_argument, 0, 's' },
|
||||||
{ "verbose", no_argument, 0, 'v' },
|
{ "verbose", no_argument, 0, 'v' },
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
while ((opt = getopt_long(argc, argv, "a::bd:Dhlqrv", long_options, &option_index)) != -1) {
|
while ((opt = getopt_long(argc, argv, "a::bd:Dhlqrsv", long_options, &option_index)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'a':
|
case 'a':
|
||||||
// toybox modprobe supported -a to load multiple modules, this
|
// toybox modprobe supported -a to load multiple modules, this
|
||||||
|
@ -113,8 +123,7 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
check_mode();
|
check_mode();
|
||||||
if (optarg == NULL) break;
|
if (optarg == NULL) break;
|
||||||
if (!android::base::ReadFileToString(optarg, &mods)) {
|
if (!android::base::ReadFileToString(optarg, &mods)) {
|
||||||
std::cerr << "Failed to open " << optarg << ": " << strerror(errno)
|
PLOG(ERROR) << "Failed to open " << optarg;
|
||||||
<< std::endl;
|
|
||||||
rv = EXIT_FAILURE;
|
rv = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
for (auto mod : android::base::Split(stripComments(mods), "\n")) {
|
for (auto mod : android::base::Split(stripComments(mods), "\n")) {
|
||||||
|
@ -135,24 +144,33 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
mode = ShowDependenciesMode;
|
mode = ShowDependenciesMode;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
android::base::SetMinimumLogSeverity(android::base::INFO);
|
||||||
print_usage();
|
print_usage();
|
||||||
return EXIT_SUCCESS;
|
return rv;
|
||||||
case 'l':
|
case 'l':
|
||||||
check_mode();
|
check_mode();
|
||||||
mode = ListModulesMode;
|
mode = ListModulesMode;
|
||||||
break;
|
break;
|
||||||
case 'q':
|
case 'q':
|
||||||
verbose = false;
|
android::base::SetMinimumLogSeverity(android::base::WARNING);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
check_mode();
|
check_mode();
|
||||||
mode = RemoveModulesMode;
|
mode = RemoveModulesMode;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
syslog = true;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose = true;
|
if (android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
|
||||||
|
android::base::SetMinimumLogSeverity(android::base::VERBOSE);
|
||||||
|
} else {
|
||||||
|
android::base::SetMinimumLogSeverity(android::base::DEBUG);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cerr << "Unrecognized option: " << opt << std::endl;
|
LOG(ERROR) << "Unrecognized option: " << opt;
|
||||||
|
print_usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,39 +189,33 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
LOG(DEBUG) << "mode is " << mode;
|
||||||
std::cout << "mode is " << mode << std::endl;
|
LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
|
||||||
std::cout << "verbose is " << verbose << std::endl;
|
LOG(DEBUG) << "modules is: " << android::base::Join(modules, " ");
|
||||||
std::cout << "mod_dirs is: " << android::base::Join(mod_dirs, " ") << std::endl;
|
LOG(DEBUG) << "module parameters is: " << android::base::Join(module_parameters, " ");
|
||||||
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 (modules.empty()) {
|
||||||
if (mode == ListModulesMode) {
|
if (mode == ListModulesMode) {
|
||||||
// emulate toybox modprobe list with no pattern (list all)
|
// emulate toybox modprobe list with no pattern (list all)
|
||||||
modules.emplace_back("*");
|
modules.emplace_back("*");
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "No modules given." << std::endl;
|
LOG(ERROR) << "No modules given.";
|
||||||
print_usage();
|
print_usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mod_dirs.empty()) {
|
if (mod_dirs.empty()) {
|
||||||
std::cerr << "No module configuration directories given." << std::endl;
|
LOG(ERROR) << "No module configuration directories given.";
|
||||||
print_usage();
|
print_usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (parameter_count && modules.size() > 1) {
|
if (parameter_count && modules.size() > 1) {
|
||||||
std::cerr << "Only one module may be loaded when specifying module parameters."
|
LOG(ERROR) << "Only one module may be loaded when specifying module parameters.";
|
||||||
<< std::endl;
|
|
||||||
print_usage();
|
print_usage();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Modprobe m(mod_dirs);
|
Modprobe m(mod_dirs);
|
||||||
m.EnableVerbose(verbose);
|
|
||||||
if (blocklist) {
|
if (blocklist) {
|
||||||
m.EnableBlocklist(true);
|
m.EnableBlocklist(true);
|
||||||
}
|
}
|
||||||
|
@ -212,19 +224,19 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case AddModulesMode:
|
case AddModulesMode:
|
||||||
if (!m.LoadWithAliases(module, true, module_parameters)) {
|
if (!m.LoadWithAliases(module, true, module_parameters)) {
|
||||||
std::cerr << "Failed to load module " << module << std::endl;
|
PLOG(ERROR) << "Failed to load module " << module;
|
||||||
rv = EXIT_FAILURE;
|
rv = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RemoveModulesMode:
|
case RemoveModulesMode:
|
||||||
if (!m.Remove(module)) {
|
if (!m.Remove(module)) {
|
||||||
std::cerr << "Failed to remove module " << module << std::endl;
|
PLOG(ERROR) << "Failed to remove module " << module;
|
||||||
rv = EXIT_FAILURE;
|
rv = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ListModulesMode: {
|
case ListModulesMode: {
|
||||||
std::vector<std::string> list = m.ListModules(module);
|
std::vector<std::string> list = m.ListModules(module);
|
||||||
std::cout << android::base::Join(list, "\n") << std::endl;
|
LOG(INFO) << android::base::Join(list, "\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ShowDependenciesMode: {
|
case ShowDependenciesMode: {
|
||||||
|
@ -235,17 +247,17 @@ extern "C" int modprobe_main(int argc, char** argv) {
|
||||||
rv = EXIT_FAILURE;
|
rv = EXIT_FAILURE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
std::cout << "Dependencies for " << module << ":" << std::endl;
|
LOG(INFO) << "Dependencies for " << module << ":";
|
||||||
std::cout << "Soft pre-dependencies:" << std::endl;
|
LOG(INFO) << "Soft pre-dependencies:";
|
||||||
std::cout << android::base::Join(pre_deps, "\n") << std::endl;
|
LOG(INFO) << android::base::Join(pre_deps, "\n");
|
||||||
std::cout << "Hard dependencies:" << std::endl;
|
LOG(INFO) << "Hard dependencies:";
|
||||||
std::cout << android::base::Join(deps, "\n") << std::endl;
|
LOG(INFO) << android::base::Join(deps, "\n");
|
||||||
std::cout << "Soft post-dependencies:" << std::endl;
|
LOG(INFO) << "Soft post-dependencies:";
|
||||||
std::cout << android::base::Join(post_deps, "\n") << std::endl;
|
LOG(INFO) << android::base::Join(post_deps, "\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
std::cerr << "Bad mode" << std::endl;
|
LOG(ERROR) << "Bad mode";
|
||||||
rv = EXIT_FAILURE;
|
rv = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue