mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-22 09:19:03 +00:00
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.
122 lines
3.8 KiB
C++
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);
|
|
}
|