mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-19 12:34:31 -04:00
162 lines
5.2 KiB
C++
162 lines
5.2 KiB
C++
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include <endpoints/deviceInfo/DeviceInfoEndpointCommon.hpp>
|
|
#include <endpoints/message/Sender.hpp>
|
|
|
|
#include <service-desktop/ServiceDesktop.hpp>
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
namespace sdesktop::endpoints
|
|
{
|
|
auto DeviceInfoEndpointCommon::handle(Context &context) -> void
|
|
{
|
|
http::Code status;
|
|
switch (context.getMethod()) {
|
|
case http::Method::get:
|
|
status = handleGet(context);
|
|
break;
|
|
default:
|
|
status = http::Code::BadRequest;
|
|
break;
|
|
}
|
|
context.setResponseStatus(status);
|
|
sender::putToSendQueue(context.createSimpleResponse());
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::handleGet(Context &context) -> http::Code
|
|
{
|
|
const auto &requestBody = context.getBody();
|
|
if (not requestBody.object_items().empty() and requestBody[json::fileList].is_number()) {
|
|
|
|
const auto diagFileType = parseDiagnosticFileType(requestBody[json::fileList]);
|
|
|
|
if (!magic_enum::enum_contains<DiagnosticFileType>(diagFileType)) {
|
|
LOG_ERROR("Bad diagnostic type %d requested", static_cast<unsigned>(diagFileType));
|
|
|
|
return http::Code::BadRequest;
|
|
}
|
|
return gatherListOfDiagnostics(context, diagFileType);
|
|
}
|
|
|
|
return getDeviceInfo(context);
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::parseDiagnosticFileType(const json11::Json &fileList) -> DiagnosticFileType
|
|
{
|
|
return magic_enum::enum_cast<DiagnosticFileType>(fileList.int_value()).value();
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::gatherListOfDiagnostics(Context &context, DiagnosticFileType diagDataType)
|
|
-> http::Code
|
|
{
|
|
std::vector<std::string> fileList;
|
|
auto status = http::Code::NoContent;
|
|
|
|
try {
|
|
requestLogsFlush();
|
|
}
|
|
catch (const std::runtime_error &e) {
|
|
LOG_ERROR("Logs flush exception: %s", e.what());
|
|
}
|
|
|
|
switch (diagDataType) {
|
|
case DiagnosticFileType::Logs: {
|
|
fileList = listDirectory(purefs::dir::getLogsPath());
|
|
break;
|
|
}
|
|
|
|
case DiagnosticFileType::CrashDumps: {
|
|
fileList = listDirectory(purefs::dir::getCrashDumpsPath());
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fileList.empty()) {
|
|
status = http::Code::OK;
|
|
context.setResponseBody(fileListToJsonObject(fileList));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::requestLogsFlush() const -> void
|
|
{
|
|
auto owner = dynamic_cast<ServiceDesktop *>(ownerServicePtr);
|
|
if (owner) {
|
|
owner->requestLogsFlush();
|
|
}
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::fileListToJsonObject(const std::vector<std::string> &fileList) const
|
|
-> json11::Json::object const
|
|
{
|
|
json11::Json::array fileArray;
|
|
|
|
for (const auto &file : fileList) {
|
|
fileArray.push_back(file);
|
|
}
|
|
|
|
return json11::Json::object{{json::files, fileArray}};
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::listDirectory(const std::string &path) -> std::vector<std::string>
|
|
{
|
|
std::vector<std::string> entries;
|
|
|
|
for (const auto &entry : std::filesystem::directory_iterator(path)) {
|
|
entries.push_back(entry.path());
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::getStorageStats(const std::string &path) -> std::tuple<long, long>
|
|
{
|
|
std::unique_ptr<struct statvfs> vfstat = std::make_unique<struct statvfs>();
|
|
if (statvfs(path.c_str(), vfstat.get()) < 0) {
|
|
return {-1, -1};
|
|
}
|
|
|
|
unsigned long totalMbytes = (uint64_t(vfstat->f_blocks) * uint64_t(vfstat->f_bsize)) / (1024LLU * 1024LLU);
|
|
unsigned long freeMbytes = (uint64_t(vfstat->f_bfree) * uint64_t(vfstat->f_bsize)) / (1024LLU * 1024LLU);
|
|
|
|
return {totalMbytes, freeMbytes};
|
|
}
|
|
|
|
auto DeviceInfoEndpointCommon::getStorageInfo() -> std::tuple<long, long, long>
|
|
{
|
|
unsigned long totalDeviceSpaceMiB = 0;
|
|
unsigned long reservedSystemSpaceMiB = 0;
|
|
unsigned long usedUserSpaceMiB = 0;
|
|
|
|
const std::array<std::filesystem::path, 1> systemStoragePaths{purefs::dir::getSystemDiskPath()};
|
|
for (const auto &p : systemStoragePaths) {
|
|
auto [totalSpace, freeSpace] = getStorageStats(p);
|
|
|
|
if (totalSpace < 0 || freeSpace < 0) {
|
|
LOG_ERROR("Failed to get stats for %s", p.c_str());
|
|
continue;
|
|
}
|
|
|
|
totalDeviceSpaceMiB += totalSpace;
|
|
reservedSystemSpaceMiB = totalDeviceSpaceMiB;
|
|
}
|
|
|
|
// User partition stats
|
|
const auto userStoragePath = purefs::dir::getUserDiskPath();
|
|
auto [totalSpace, freeSpace] = getStorageStats(userStoragePath);
|
|
|
|
if (totalSpace < 0 || freeSpace < 0) {
|
|
LOG_ERROR("Failed to get stats for %s", userStoragePath.c_str());
|
|
}
|
|
else {
|
|
usedUserSpaceMiB = totalSpace - freeSpace;
|
|
totalDeviceSpaceMiB += totalSpace;
|
|
}
|
|
|
|
return {totalDeviceSpaceMiB, reservedSystemSpaceMiB, usedUserSpaceMiB};
|
|
}
|
|
} // namespace sdesktop::endpoints
|