diff --git a/cpp/base/property_handler.cpp b/cpp/base/property_handler.cpp index 35494837..e8acdb35 100644 --- a/cpp/base/property_handler.cpp +++ b/cpp/base/property_handler.cpp @@ -170,3 +170,21 @@ map> PropertyHandler::GetCustomModePages(const string &vendor, return pages; } + +bool PropertyHandler::Persist() const +{ + error_code error; + remove(GLOBAL_CONFIGURATION + ".old", error); + rename(path(GLOBAL_CONFIGURATION), path(GLOBAL_CONFIGURATION + ".old"), error); + + ofstream out(GLOBAL_CONFIGURATION); + for (const auto& [key, value] : GetProperties()) { + out << key << "=" << value << "\n"; + if (out.fail()) { + return false; + } + } + + return true; +} + diff --git a/cpp/base/property_handler.h b/cpp/base/property_handler.h index 7912e48e..37ce05c0 100644 --- a/cpp/base/property_handler.h +++ b/cpp/base/property_handler.h @@ -51,6 +51,8 @@ class PropertyHandler map> GetCustomModePages(const string&, const string&) const; + bool Persist() const; + private: PropertyHandler() = default; diff --git a/cpp/command/command_dispatcher.cpp b/cpp/command/command_dispatcher.cpp index 6d3b715d..03bf8ece 100644 --- a/cpp/command/command_dispatcher.cpp +++ b/cpp/command/command_dispatcher.cpp @@ -6,6 +6,7 @@ // //--------------------------------------------------------------------------- +#include #include #include "controllers/controller_factory.h" #include "shared/shared_exceptions.h" @@ -144,6 +145,14 @@ bool CommandDispatcher::DispatchCommand(const CommandContext &context, PbResult case RESERVE_IDS: return executor.ProcessCmd(context); + case PERSIST_CONFIGURATION: + if (PropertyHandler::Instance().Persist()) { + return context.ReturnSuccessStatus(); + } + else { + return context.ReturnLocalizedError(LocalizationKey::ERROR_PERSIST); + } + default: // The remaining commands may only be executed when the target is idle if (!ExecuteWithLock(context)) { diff --git a/cpp/command/command_response.cpp b/cpp/command/command_response.cpp index 71c9c692..de9fec62 100644 --- a/cpp/command/command_response.cpp +++ b/cpp/command/command_response.cpp @@ -398,8 +398,6 @@ void CommandResponse::GetOperationInfo(PbOperationInfo &operation_info, int dept CreateOperation(operation_info, STATISTICS_INFO, "Get statistics"); - CreateOperation(operation_info, PROPERTIES_INFO, "Get properties"); - CreateOperation(operation_info, RESERVED_IDS_INFO, "Get list of reserved device IDs"); operation = CreateOperation(operation_info, DEFAULT_FOLDER, "Set default image file folder"); @@ -446,6 +444,10 @@ void CommandResponse::GetOperationInfo(PbOperationInfo &operation_info, int dept operation = CreateOperation(operation_info, CHECK_AUTHENTICATION, "Check whether an authentication token is valid"); AddOperationParameter(*operation, "token", "Authentication token to be checked", "", true); + CreateOperation(operation_info, PROPERTIES_INFO, "Get current s2p properties"); + + CreateOperation(operation_info, PERSIST_CONFIGURATION, "Save current configuration to /etc/s2p.conf"); + CreateOperation(operation_info, OPERATION_INFO, "Get operation meta data"); } diff --git a/cpp/s2pctl/sp2ctl_core.cpp b/cpp/s2pctl/sp2ctl_core.cpp index 0d73caaf..9fb3deef 100644 --- a/cpp/s2pctl/sp2ctl_core.cpp +++ b/cpp/s2pctl/sp2ctl_core.cpp @@ -77,6 +77,7 @@ void S2pCtl::Banner(bool usage) const << " s2p requires authentication.\n" << " --list-settings/-s List s2p settings.\n" << " --list-statistics/-S List s2p statistics.\n" + << " --persist Save the current configuration to /etc/s2p.conf.\n" << " --version/-v Display the program version.\n" << " --server-version/-V Display the s2p server version.\n" << " --shut-down/-X Shut down s2p.\n"; @@ -132,6 +133,7 @@ int S2pCtl::ParseArguments(const vector &args) // NOSONAR Acceptable comp const int OPT_LOCALE = 7; const int OPT_SCSI_LEVEL = 8; const int OPT_LIST_EXTENSIONS = 9; + const int OPT_PERSIST = 10; const vector