blob: 365fb1782b97433fa9caa5a54803815414e853aa [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "modemloggerd/modem.h"
#include <csignal>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include "modemloggerd/dbus-constants.h"
#include "modemloggerd/logging_prefs.h"
namespace {
const char kVarLog[] = "/var/log/modemloggerd";
}
namespace modemloggerd {
Modem::Modem(dbus::Bus* bus,
AdaptorFactoryInterface* adaptor_factory,
HelperEntry logging_helper)
: output_dir_(kVarLog),
dbus_adaptor_(adaptor_factory->CreateModemAdaptor(this, bus)),
logging_helper_(logging_helper) {
LOG(INFO) << __func__ << ": " << logging_helper_.exe().filename();
if (!LoggingPrefs::Get()->GetAutoStart(logging_helper_.modem_name())) {
return;
}
auto start_result = Start();
if (start_result != nullptr) {
LOG(ERROR) << "Failed to auto start logger: " << start_result->GetMessage();
}
}
brillo::ErrorPtr Modem::SetEnabled(bool enable) {
LOG(INFO) << __func__ << ": " << enable;
if ((enable && !logging_helper_.has_enable_exe()) ||
(!enable && !logging_helper_.has_disable_exe())) {
return nullptr;
}
const int exit_code = RunEnableHelper(enable);
if (exit_code == 0) {
return nullptr;
}
return brillo::Error::Create(
FROM_HERE, brillo::errors::dbus::kDomain, kErrorOperationFailed,
base::StringPrintf("Failed to run helper (exit_code=%d)", exit_code));
}
brillo::ErrorPtr Modem::SetAutoStart(bool autostart) {
LOG(INFO) << __func__ << ": " << autostart;
if (!LoggingPrefs::Get()->SetAutoStart(logging_helper_.modem_name(),
autostart)) {
return brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain,
kErrorOperationFailed,
"Failed to set auto start");
}
return nullptr;
}
brillo::ErrorPtr Modem::Start() {
// TODO(pholla): Sandbox if daemon moves into release images
LOG(INFO) << __func__;
if (StartLoggingHelper()) {
return nullptr;
}
return brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain,
kErrorOperationFailed, "Failed to start logger");
}
brillo::ErrorPtr Modem::Stop() {
LOG(INFO) << __func__;
const int kStopTimeoutSeconds = 2;
if (logger_process_.Kill(SIGKILL, kStopTimeoutSeconds)) {
return nullptr;
}
return brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain,
kErrorOperationFailed, "Failed to stop logger");
}
bool Modem::StartLoggingHelper() {
logger_process_.AddArg(logging_helper_.exe().filename());
for (const std::string& extra_argument :
logging_helper_.exe().extra_argument()) {
logger_process_.AddArg(extra_argument);
}
if (logging_helper_.exe().has_output_dir_argument()) {
logger_process_.AddArg(logging_helper_.exe().output_dir_argument());
logger_process_.AddArg(output_dir_);
}
logger_process_.RedirectOutput(GetLogPath(logging_helper_.exe().filename()));
return logger_process_.Start();
}
int Modem::RunEnableHelper(bool enable) {
auto exe =
enable ? logging_helper_.enable_exe() : logging_helper_.disable_exe();
brillo::ProcessImpl process;
process.AddArg(exe.filename());
for (const std::string& extra_argument : exe.extra_argument()) {
process.AddArg(extra_argument);
}
process.RedirectOutput(GetLogPath(exe.filename()));
return process.Run();
}
std::string Modem::GetLogPath(const std::string& filename) {
const std::string log_prefix =
base::FilePath(filename).BaseName().MaybeAsASCII();
base::Time::Exploded time;
base::Time::Now().LocalExplode(&time);
return base::StringPrintf("%s/%s_log.%4u%02u%02u-%02u%02u%02u%03u",
output_dir_.c_str(), log_prefix.c_str(), time.year,
time.month, time.day_of_month, time.hour,
time.minute, time.second, time.millisecond);
}
dbus::ObjectPath Modem::GetDBusPath() {
return dbus_adaptor_->object_path();
}
brillo::ErrorPtr Modem::SetOutputDir(const std::string& output_dir) {
LOG(INFO) << __func__ << ": " << output_dir;
output_dir_ = output_dir;
return nullptr;
}
} // namespace modemloggerd