Files
ladybird/Userland/Utilities/sysctl.cpp
Tim Schumacher d5871f5717 AK: Rename Stream::{read,write} to Stream::{read_some,write_some}
Similar to POSIX read, the basic read and write functions of AK::Stream
do not have a lower limit of how much data they read or write (apart
from "none at all").

Rename the functions to "read some [data]" and "write some [data]" (with
"data" being omitted, since everything here is reading and writing data)
to make them sufficiently distinct from the functions that ensure to
use the entire buffer (which should be the go-to function for most
usages).

No functional changes, just a lot of new FIXMEs.
2023-03-13 15:16:20 +00:00

122 lines
3.8 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Alex Major
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/ArgsParser.h>
#include <LibCore/DirIterator.h>
#include <LibCore/File.h>
#include <LibMain/Main.h>
static bool s_set_variable = false;
static DeprecatedString get_variable(StringView name)
{
auto path = DeprecatedString::formatted("/sys/kernel/variables/{}", name);
auto file = Core::File::open(path, Core::File::OpenMode::Read);
if (file.is_error()) {
warnln("Failed to open {}: {}", path, file.error());
return {};
}
auto buffer = file.value()->read_until_eof();
if (buffer.is_error()) {
warnln("Failed to read {}: {}", path, buffer.error());
return {};
}
return { (char const*)buffer.value().data(), buffer.value().size(), Chomp };
}
static bool read_variable(StringView name)
{
auto value = get_variable(name);
if (value.is_null())
return false;
outln("{} = {}", name, value);
return true;
}
static bool write_variable(StringView name, StringView value)
{
auto old_value = get_variable(name);
if (old_value.is_null())
return false;
auto path = DeprecatedString::formatted("/sys/kernel/variables/{}", name);
auto file = Core::File::open(path, Core::File::OpenMode::Write);
if (file.is_error()) {
warnln("Failed to open {}: {}", path, file.error());
return false;
}
// FIXME: This should write the entire span.
if (auto result = file.value()->write_some(value.bytes()); result.is_error()) {
warnln("Failed to write {}: {}", path, result.error());
return false;
}
outln("{}: {} -> {}", name, old_value, value);
return true;
}
static int handle_variables(Vector<StringView> const& variables)
{
bool success = false;
for (auto const& variable : variables) {
auto maybe_index = variable.find('=');
if (!maybe_index.has_value()) {
success = read_variable(variable);
continue;
}
auto equal_index = maybe_index.release_value();
auto name = variable.substring_view(0, equal_index);
auto value = variable.substring_view(equal_index + 1, variable.length() - equal_index - 1);
if (name.is_empty())
warnln("Malformed setting '{}'", variable);
else if (!s_set_variable)
warnln("Must specify '-w' to set variables");
else
success = write_variable(name, value);
}
return success ? 0 : 1;
}
static int handle_show_all()
{
Core::DirIterator di("/sys/kernel/variables", Core::DirIterator::SkipDots);
if (di.has_error()) {
outln("DirIterator: {}", di.error());
return 1;
}
bool success = false;
while (di.has_next()) {
auto name = di.next_path();
success = read_variable(name);
}
return success ? 0 : 1;
}
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
bool show_all = false;
Vector<StringView> variables;
Core::ArgsParser args_parser;
args_parser.set_general_help("Show or modify system-internal values. This requires root, and can crash your system.");
args_parser.add_option(show_all, "Show all variables", "all", 'a');
args_parser.add_option(s_set_variable, "Set variables", "write", 'w');
args_parser.add_positional_argument(variables, "variable[=value]", "variables", Core::ArgsParser::Required::No);
args_parser.parse(arguments);
if (!show_all && variables.is_empty()) {
args_parser.print_usage(stdout, arguments.strings[0]);
return 1;
}
if (show_all) {
// Ignore `variables`, even if they are supplied. Just like the real procps does.
return handle_show_all();
}
return handle_variables(variables);
}