From 6ab09d5ffd058c85484bd9dcd6f3cc9d865549bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ta=C5=84ski?= Date: Mon, 6 Sep 2021 17:03:25 +0200 Subject: [PATCH] [EGD-7459] Fixed factory reset process Fixed the factory reset process. --- .../windows/system/SystemMainWindow.cpp | 4 +- .../model/ApplicationManagerCommon.cpp | 2 + .../service-db/ServiceDBCommon.cpp | 24 ++ .../include/service-db/ServiceDBCommon.hpp | 3 + .../service-desktop/CMakeLists.txt | 1 - .../service-desktop/ServiceDesktop.cpp | 3 +- .../endpoints/factoryReset/FactoryReset.cpp | 238 ------------------ .../endpoints/factoryReset/FactoryReset.hpp | 20 -- .../service-desktop/tests/unittest.cpp | 1 - module-sys/Service/Common.hpp | 1 + .../SystemManager/SystemManagerCommon.cpp | 12 +- .../SystemManager/SystemManagerCommon.hpp | 3 + 12 files changed, 46 insertions(+), 266 deletions(-) delete mode 100644 module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp delete mode 100644 module-services/service-desktop/endpoints/factoryReset/FactoryReset.hpp diff --git a/module-apps/application-settings/windows/system/SystemMainWindow.cpp b/module-apps/application-settings/windows/system/SystemMainWindow.cpp index 6f87cfaabac57b4231d8e98399e36d96869a092a..0e9a5d12762befac27f5066fe43a4a6ad7533abd 100644 --- a/module-apps/application-settings/windows/system/SystemMainWindow.cpp +++ b/module-apps/application-settings/windows/system/SystemMainWindow.cpp @@ -41,9 +41,7 @@ namespace gui utils::translate("app_settings_display_factory_reset_confirmation"), "", [this]() { - auto msg = std::make_shared(); - application->bus.sendUnicast(msg, service::name::service_desktop); - application->returnToPreviousWindow(2); + sys::SystemManagerCommon::FactoryReset(application); return true; }}); LOG_INFO("switching to %s page", window.c_str()); diff --git a/module-services/service-appmgr/model/ApplicationManagerCommon.cpp b/module-services/service-appmgr/model/ApplicationManagerCommon.cpp index 72eda48b29ec9f362048a1842c2e40850cfc65d1..ffa1818ce6548f364d1b174047adeecb96a98740 100644 --- a/module-services/service-appmgr/model/ApplicationManagerCommon.cpp +++ b/module-services/service-appmgr/model/ApplicationManagerCommon.cpp @@ -163,6 +163,8 @@ namespace app::manager case sys::CloseReason::RegularPowerDown: [[fallthrough]]; case sys::CloseReason::Reboot: + [[fallthrough]]; + case sys::CloseReason::FactoryReset: break; } handleActionRequest(&act); diff --git a/module-services/service-db/ServiceDBCommon.cpp b/module-services/service-db/ServiceDBCommon.cpp index 7829eccd072a47083f79d0597aa85785a80adffe..c5bad89998569f507cd42a774f89b8f3d30b8b2b 100644 --- a/module-services/service-db/ServiceDBCommon.cpp +++ b/module-services/service-db/ServiceDBCommon.cpp @@ -6,6 +6,8 @@ #include #include +#include + static const auto service_db_stack = 1024 * 24; ServiceDBCommon::ServiceDBCommon() : sys::Service(service::name::db, "", service_db_stack, sys::ServicePriority::Idle) @@ -63,9 +65,31 @@ sys::ReturnCodes ServiceDBCommon::DeinitHandler() void ServiceDBCommon::ProcessCloseReason(sys::CloseReason closeReason) { + if (closeReason == sys::CloseReason::FactoryReset) { + factoryReset(); + } sendCloseReadyMessage(this); } +void ServiceDBCommon::factoryReset() const +{ + constexpr std::array fileExtensions = {".db", ".db-journal", ".db-wal"}; + + LOG_INFO("Performing DB factory reset..."); + const auto userOSPath = purefs::dir::getUserDiskPath(); + for (const auto &f : std::filesystem::directory_iterator(userOSPath)) { + if (const auto it = std::find(fileExtensions.begin(), fileExtensions.end(), f.path().extension()); + it != fileExtensions.end()) { + if (const auto removeStatus = std::filesystem::remove(f.path()); !removeStatus) { + LOG_ERROR("Unable to delete file: %s", f.path().c_str()); + } + else { + LOG_INFO("File deleted: %s", f.path().c_str()); + } + } + } +} + sys::ReturnCodes ServiceDBCommon::SwitchPowerModeHandler(const sys::ServicePowerMode mode) { LOG_FATAL("[%s] PowerModeHandler: %s", this->GetName().c_str(), c_str(mode)); diff --git a/module-services/service-db/include/service-db/ServiceDBCommon.hpp b/module-services/service-db/include/service-db/ServiceDBCommon.hpp index ed2fc5dc05e00d69d60cab618cd96450f5d8b89b..2c22a7e9ca2169722f1127ecbfb960b6c4d710dd 100644 --- a/module-services/service-db/include/service-db/ServiceDBCommon.hpp +++ b/module-services/service-db/include/service-db/ServiceDBCommon.hpp @@ -11,6 +11,9 @@ class ServiceDBCommon : public sys::Service { + private: + void factoryReset() const; + protected: virtual db::Interface *getInterface(db::Interface::Name interface); std::set> databaseAgents; diff --git a/module-services/service-desktop/CMakeLists.txt b/module-services/service-desktop/CMakeLists.txt index efd4ac7fb11970e4e8b99c011e7f3d4ae5af611f..2da8959853303433d297c57c6ef9421e3ebf66f3 100644 --- a/module-services/service-desktop/CMakeLists.txt +++ b/module-services/service-desktop/CMakeLists.txt @@ -22,7 +22,6 @@ set(SOURCES endpoints/developerMode/event/DomRequest.cpp endpoints/developerMode/event/ATRequest.cpp endpoints/deviceInfo/DeviceInfoEndpoint.cpp - endpoints/factoryReset/FactoryReset.cpp endpoints/factoryReset/FactoryResetEndpoint.cpp endpoints/messages/MessageHelper.cpp endpoints/messages/MessagesEndpoint.cpp diff --git a/module-services/service-desktop/ServiceDesktop.cpp b/module-services/service-desktop/ServiceDesktop.cpp index 4e1ce65a660d35cde6cea01845aa024a71dec8c8..5ad0c15a21301f2d49913e08a1e47bd63d49c104 100644 --- a/module-services/service-desktop/ServiceDesktop.cpp +++ b/module-services/service-desktop/ServiceDesktop.cpp @@ -6,7 +6,6 @@ #include "service-desktop/ServiceDesktop.hpp" #include "service-desktop/WorkerDesktop.hpp" #include "service-cellular/CellularMessage.hpp" -#include "endpoints/factoryReset/FactoryReset.hpp" #include "endpoints/backup/BackupRestore.hpp" #include @@ -143,7 +142,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler() auto *factoryMessage = dynamic_cast(msg); if (factoryMessage != nullptr) { LOG_DEBUG("ServiceDesktop: FactoryMessage received"); - FactoryReset::Run(this); + sys::SystemManagerCommon::FactoryReset(this); } return sys::MessageNone{}; }); diff --git a/module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp b/module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp deleted file mode 100644 index afc99bd1ec1ced9805f4823f21117aa0ad404c6c..0000000000000000000000000000000000000000 --- a/module-services/service-desktop/endpoints/factoryReset/FactoryReset.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#include "FactoryReset.hpp" -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace sys -{ - class Service; -} // namespace sys - -namespace FactoryReset -{ - namespace - { - inline constexpr auto copy_buf = 8192 * 4; - } // namespace - - static bool CopyFile(const std::string &sourcefile, const std::string &targetfile); - - static int recurseDepth = 0; - static const int max_recurse_depth = 120; /* 120 is just an arbitrary value of max number of recursive calls. - * If more then error is assumed, not the real depth of directories." - */ - static const int max_filepath_length = PATH_MAX; - - bool Run(sys::Service *ownerService) - { - LOG_INFO("Restoring factory state started..."); - - recurseDepth = 0; - const auto userOSPath = purefs::dir::getUserDiskPath(); - - if (std::filesystem::is_directory(userOSPath.c_str()) && std::filesystem::is_empty(userOSPath.c_str())) { - LOG_ERROR("Restoring factory state aborted"); - LOG_ERROR("Directory %s seems empty.", userOSPath.c_str()); - return false; - } - - if (ownerService != nullptr) { - LOG_INFO("Closing ServiceDB..."); - std::string dbServiceName = service::name::db; - sys::SystemManagerCommon::DestroySystemService(dbServiceName, ownerService); - } - - DeleteSelectedUserFiles(userOSPath); - - LOG_INFO("Rebooting..."); - sys::SystemManagerCommon::Reboot(ownerService); - return true; - } - - bool DeleteSelectedUserFiles(const std::filesystem::path &userOSPath) - { - bool returnStatus = true; - std::vector selectedFileExt = {".db", ".db-journal", ".db-wal"}; - - LOG_INFO("Delete DB files which will be recreated with factory content after reboot:"); - for (const auto &f : std::filesystem::directory_iterator(userOSPath.c_str())) { - for (const auto &ext : selectedFileExt) { - if (f.path().extension() == ext) { - auto removeStatus = std::filesystem::remove(f.path()); - if (!removeStatus) { - LOG_ERROR("Error deleting file %s, aborting...", f.path().c_str()); - returnStatus = false; - } - else { - LOG_INFO("%s deleted.", f.path().c_str()); - } - break; - } - } - } - return returnStatus; - } - - bool DeleteDirContent(const std::string &dir) - { - for (auto &direntry : std::filesystem::directory_iterator(dir.c_str())) { - if (!((direntry.path().string() != ".") && (direntry.path().string() != "..") && - (direntry.path().string() != "..."))) { - continue; - } - std::string delpath = dir; - delpath += "/"; - delpath += direntry.path().string(); - - if (std::filesystem::is_directory(direntry)) { - if (direntry.path().string() != purefs::dir::getFactoryOSPath()) { - LOG_INFO("FactoryReset: recursively deleting dir..."); - try { - std::filesystem::remove_all(delpath.c_str()); - } - catch (const std::filesystem::filesystem_error &e) { - LOG_ERROR("FactoryReset: error deleting dir, aborting..."); - return false; - } - } - } - else { - LOG_INFO("FactoryReset: deleting file..."); - if (std::filesystem::remove(delpath.c_str())) { - LOG_ERROR("FactoryReset: error deleting file, aborting..."); - return false; - } - } - } - - return true; - } - - bool CopyDirContent(const std::string &sourcedir, const std::string &targetdir) - { - if (recurseDepth >= max_recurse_depth) { - LOG_ERROR("FactoryReset: recurse level %d (too high), error assumed, skipping restore of dir", - recurseDepth); - return false; - } - - const auto factoryOSPath = purefs::dir::getFactoryOSPath(); - - for (auto &direntry : std::filesystem::directory_iterator(sourcedir.c_str())) { - if ((direntry.path().string() == ".") || (direntry.path().string() == "..") || - (direntry.path().string() == "...")) { - continue; - } - - std::string sourcepath = sourcedir; - sourcepath += "/"; - sourcepath += direntry.path().string(); - - std::string targetpath = targetdir; - targetpath += "/"; - targetpath += direntry.path().string(); - - if ((sourcepath.size() >= max_filepath_length) || (targetpath.size() >= max_filepath_length)) { - LOG_ERROR("FactoryReset: path length (source or target) exceeds system limit of %d", - max_filepath_length); - LOG_ERROR("FactoryReset: skipping restore of directory"); - return false; - } - - if (std::filesystem::is_directory(direntry)) { - if (targetpath == factoryOSPath) { - continue; - } - - LOG_INFO("FactoryReset: restoring directory"); - - try { - if (std::filesystem::create_directory(targetpath.c_str())) { - LOG_ERROR("FactoryReset: create dir failed"); - return false; - } - } - catch (const std::filesystem::filesystem_error &err) { - LOG_FATAL("Exception while creating dir"); - return false; - } - - recurseDepth++; - - if (!CopyDirContent(sourcepath, targetpath)) { - recurseDepth--; - return false; - } - - recurseDepth--; - } - else { - LOG_INFO("FactoryReset: restoring file"); - - if (!CopyFile(sourcepath, targetpath)) { - return false; - } - } - } - - return true; - } - - static bool CopyFile(const std::string &sourcefile, const std::string &targetfile) - { - bool ret = true; - auto lamb = [](std::FILE *stream) { std::fclose(stream); }; - - std::unique_ptr sf(std::fopen(sourcefile.c_str(), "r"), lamb); - std::unique_ptr tf(std::fopen(targetfile.c_str(), "w"), lamb); - - if (sf && tf) { - std::unique_ptr buffer(new unsigned char[copy_buf]); - - if (buffer) { - uint32_t loopcount = (std::filesystem::file_size(sourcefile) / copy_buf) + 1u; - uint32_t readsize = copy_buf; - - for (uint32_t i = 0u; i < loopcount; i++) { - if (i + 1u == loopcount) { - readsize = std::filesystem::file_size(sourcefile) % copy_buf; - } - - if (std::fread(buffer.get(), 1, readsize, sf.get()) != readsize) { - LOG_ERROR("FactoryReset: read from sourcefile failed"); - ret = false; - break; - } - - if (std::fwrite(buffer.get(), 1, readsize, tf.get()) != readsize) { - LOG_ERROR("FactoryReset: write to targetfile failed"); - ret = false; - break; - } - } - } - else { - LOG_ERROR("FactoryReset: unable to open copy buffer"); - ret = false; - } - } - else { - LOG_ERROR("FactoryReset: unable to open source or target file"); - ret = false; - } - - return ret; - } -} // namespace FactoryReset diff --git a/module-services/service-desktop/endpoints/factoryReset/FactoryReset.hpp b/module-services/service-desktop/endpoints/factoryReset/FactoryReset.hpp deleted file mode 100644 index 085a52443f162ae16b5510d34b1443c9725dc4bc..0000000000000000000000000000000000000000 --- a/module-services/service-desktop/endpoints/factoryReset/FactoryReset.hpp +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. -// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -#pragma once -#include -#include -#include - -namespace sys -{ - class Service; -} // namespace sys - -namespace FactoryReset -{ - bool Run(sys::Service *ownerService); - bool DeleteSelectedUserFiles(const std::filesystem::path &userOSPath); - bool DeleteDirContent(const std::string &dir); - bool CopyDirContent(const std::string &sourcedir, const std::string &targetdir); -} // namespace FactoryReset diff --git a/module-services/service-desktop/tests/unittest.cpp b/module-services/service-desktop/tests/unittest.cpp index c8015460ae7a566062c652df9b0059ffdc3884da..c4e40c82bbdcdd14fb7046a96fecc662f2d6b928 100644 --- a/module-services/service-desktop/tests/unittest.cpp +++ b/module-services/service-desktop/tests/unittest.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include diff --git a/module-sys/Service/Common.hpp b/module-sys/Service/Common.hpp index 4ea021a2626f909377f18f6c8fc65359aabcb649..0fe30f289c86c37df133c41e2db41fa182727908 100644 --- a/module-sys/Service/Common.hpp +++ b/module-sys/Service/Common.hpp @@ -49,6 +49,7 @@ namespace sys { RegularPowerDown, Reboot, + FactoryReset, SystemBrownout, LowBattery }; diff --git a/module-sys/SystemManager/SystemManagerCommon.cpp b/module-sys/SystemManager/SystemManagerCommon.cpp index c13be857e52e7153d25e395da2c57956b4740904..9d9c02ebbddeb7cbeaeca0362c3072c81c5db0de 100644 --- a/module-sys/SystemManager/SystemManagerCommon.cpp +++ b/module-sys/SystemManager/SystemManagerCommon.cpp @@ -232,9 +232,16 @@ namespace sys return true; } + bool SystemManagerCommon::FactoryReset(Service *s) + { + return s->bus.sendUnicast(std::make_shared(Code::FactoryReset, CloseReason::FactoryReset), + service::name::system_manager); + } + bool SystemManagerCommon::Reboot(Service *s) { - s->bus.sendUnicast(std::make_shared(Code::Reboot), service::name::system_manager); + s->bus.sendUnicast(std::make_shared(Code::Reboot, CloseReason::Reboot), + service::name::system_manager); return true; } @@ -474,6 +481,9 @@ namespace sys case Code::RebootToUpdate: RebootHandler(State::RebootToUpdate, data->updateReason); break; + case Code::FactoryReset: + CloseSystemHandler(CloseReason::FactoryReset); + break; case Code::None: break; } diff --git a/module-sys/SystemManager/SystemManagerCommon.hpp b/module-sys/SystemManager/SystemManagerCommon.hpp index a460661d79af9613dd258a520875cb256ea9651c..207b1861f209e480c977cb8b5582b1b57b4e034c 100644 --- a/module-sys/SystemManager/SystemManagerCommon.hpp +++ b/module-sys/SystemManager/SystemManagerCommon.hpp @@ -39,6 +39,7 @@ namespace sys Restore, Reboot, RebootToUpdate, + FactoryReset, None, }; @@ -92,6 +93,8 @@ namespace sys static bool Restore(Service *s); + static bool FactoryReset(Service *s); + static bool Reboot(Service *s); static bool RebootToUpdate(Service *s, UpdateReason updateReason);