// Use of this source code is governed by an apache-2.0 license that can be
// found in the LICENSE file.
-#include <glib.h>
-#include <gio/gio.h>
+#include <boost/exception/diagnostic_information.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
-#include <manifest_parser/utils/logging.h>
+#include <glib.h>
+#include <common/request.h>
#include <common/utils/subprocess.h>
+#include <common/utils/user_util.h>
+#include <manifest_parser/utils/logging.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
-#define UNUSED(expr) (void)(expr)
+#include <regex>
+#include <string>
+#include <vector>
+namespace bf = boost::filesystem;
namespace ci = common_installer;
namespace {
-const char kDBusInstropectionXml[] =
- "<node>"
- " <interface name='org.tizen.pkg_recovery'>"
- " <method name='RecoverPkg'>"
- " <arg type='u' name='uid' direction='in'/>"
- " <arg type='s' name='type' direction='in'/>"
- " <arg type='s' name='file' direction='in'/>"
- " <arg type='b' name='result' direction='out'/>"
- " </method>"
- " </interface>"
- "</node>";
-const char kDBusServiceName[] = "org.tizen.pkg_recovery";
-const char kDBusObjectPath[] = "/org/tizen/pkg_recovery";
+typedef std::pair<std::string, std::string> RecoverEntry;
+
+const char kRecoveryFilePattern[] = "^(.*)-recovery-(.*)";
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
class PkgRecoveryService {
public:
PkgRecoveryService();
~PkgRecoveryService();
- bool Init();
void Run();
private:
+ std::vector<RecoverEntry> SearchRecoveryFiles(uid_t uid);
+ void ProcessRecovery(uid_t uid, const std::vector<RecoverEntry>& entries);
bool RunBackend(uid_t uid, const char* type, const char* file);
- void Finish();
- void RenewTimeout(int ms);
- void HandleMethodCall(GDBusConnection* connection,
- const gchar* sender, const gchar* object_path,
- const gchar* interface_name, const gchar* method_name,
- GVariant* parameters, GDBusMethodInvocation* invocation,
- gpointer user_data);
- void OnBusAcquired(GDBusConnection* connection, const gchar* name,
- gpointer user_data);
-
- GDBusNodeInfo* node_info_;
- guint owner_id_;
- GMainLoop* loop_;
- guint sid_;
};
-PkgRecoveryService::PkgRecoveryService() :
- node_info_(nullptr), owner_id_(0), loop_(nullptr), sid_(0) {
+PkgRecoveryService::PkgRecoveryService() {
}
PkgRecoveryService::~PkgRecoveryService() {
- Finish();
-}
-
-bool PkgRecoveryService::Init() {
- node_info_ = g_dbus_node_info_new_for_xml(kDBusInstropectionXml, nullptr);
- if (!node_info_) {
- LOG(ERROR) << "Failed to create DBus node info";
- return false;
- }
- owner_id_ = g_bus_own_name(G_BUS_TYPE_SYSTEM, kDBusServiceName,
- G_BUS_NAME_OWNER_FLAGS_NONE,
- [](GDBusConnection* connection, const gchar* name,
- gpointer user_data) {
- reinterpret_cast<PkgRecoveryService*>(user_data)->OnBusAcquired(
- connection, name, user_data);
- },
- nullptr, nullptr, this, nullptr);
-
- loop_ = g_main_loop_new(nullptr, FALSE);
- if (!loop_) {
- LOG(ERROR) << "Failed to create main loop";
- return false;
- }
-
- RenewTimeout(5000);
-
- return true;
}
bool PkgRecoveryService::RunBackend(uid_t uid, const char* type,
}
void PkgRecoveryService::Run() {
- g_main_loop_run(loop_);
-}
-
-void PkgRecoveryService::Finish() {
- if (owner_id_ > 0)
- g_bus_unown_name(owner_id_);
- if (node_info_)
- g_dbus_node_info_unref(node_info_);
- if (loop_)
- g_main_loop_unref(loop_);
-}
-
-void PkgRecoveryService::RenewTimeout(int ms) {
- if (sid_)
- g_source_remove(sid_);
- sid_ = g_timeout_add(ms,
- [](gpointer user_data) {
- g_main_loop_quit(
- reinterpret_cast<PkgRecoveryService*>(user_data)->loop_);
- return FALSE;
- },
- this);
+ // recover global packages
+ LOG(INFO) << "Searching recovery files for user " << kGlobalUserUid;
+ std::vector<RecoverEntry> globalentries = SearchRecoveryFiles(kGlobalUserUid);
+ ProcessRecovery(kGlobalUserUid, globalentries);
+
+ // recover normal user packages
+ ci::UserList list = ci::GetUserList();
+ for (auto userinfo : list) {
+ uid_t uid = std::get<0>(userinfo);
+ LOG(INFO) << "Searching recovery files for user " << std::get<0>(userinfo);
+ std::vector<RecoverEntry> entries = SearchRecoveryFiles(uid);
+ ProcessRecovery(uid, entries);
+ }
}
-void PkgRecoveryService::HandleMethodCall(GDBusConnection* connection,
- const gchar* sender, const gchar* object_path, const gchar* interface_name,
- const gchar* method_name, GVariant* parameters,
- GDBusMethodInvocation* invocation, gpointer user_data) {
- UNUSED(connection);
- UNUSED(sender);
- UNUSED(object_path);
- UNUSED(interface_name);
- UNUSED(user_data);
- bool r = false;
-
- LOG(INFO) << "Incomming method call: " << method_name;
- if (g_strcmp0(method_name, "RecoverPkg") == 0) {
- uid_t uid;
- char* type;
- char* file;
- g_variant_get(parameters, "(u&s&s)", &uid, &type, &file);
- LOG(DEBUG) << "Recover pkg. uid: " << uid << ", type: " << type
- << ", file: " << file;
- r = RunBackend(uid, type, file);
- } else {
- LOG(ERROR) << "Unknown method call: " << method_name;
+std::vector<RecoverEntry> PkgRecoveryService::SearchRecoveryFiles(uid_t uid) {
+ std::vector<RecoverEntry> list;
+ const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
+ LOG(INFO) << "RootAppPath: " << recovery_dir;
+ for (bf::directory_iterator iter(recovery_dir);
+ iter != bf::directory_iterator();
+ ++iter) {
+ try {
+ std::string file = iter->path().filename().string();
+ std::regex recovery_regex(kRecoveryFilePattern);
+ std::smatch match;
+ if (std::regex_search(file, match, recovery_regex)) {
+ LOG(INFO) << "Found recovery file: " << file;
+ std::string type(match[1]);
+ list.emplace_back(type, iter->path().string());
+ }
+ } catch (...) {
+ LOG(WARNING) << "Exception occurred: "
+ << boost::current_exception_diagnostic_information();
+ continue;
+ }
}
- g_dbus_method_invocation_return_value(invocation, g_variant_new("(b)", r));
- RenewTimeout(5000);
+ return list;
}
-void PkgRecoveryService::OnBusAcquired(
- GDBusConnection* connection, const gchar* name, gpointer user_data) {
- UNUSED(name);
- UNUSED(user_data);
- GError* err = nullptr;
- GDBusInterfaceVTable vtable = {
- [](GDBusConnection* connection, const gchar* sender,
- const gchar* object_path, const gchar* interface_name,
- const gchar* method_name, GVariant* parameters,
- GDBusMethodInvocation* invocation, gpointer user_data) {
- reinterpret_cast<PkgRecoveryService*>(user_data)->HandleMethodCall(
- connection, sender, object_path, interface_name, method_name,
- parameters, invocation, user_data);
- },
- nullptr, nullptr, {0, }
- };
-
- guint reg_id = g_dbus_connection_register_object(connection, kDBusObjectPath,
- node_info_->interfaces[0], &vtable, this, nullptr, &err);
- if (reg_id == 0) {
- LOG(ERROR) << "Register failed";
- if (err) {
- LOG(ERROR) << "Error message: " << err->message;
- g_error_free(err);
- }
- } else {
- LOG(INFO) << "DBus service registered";
+void PkgRecoveryService::ProcessRecovery(uid_t uid,
+ const std::vector<RecoverEntry>& entries) {
+ LOG(INFO) << "Process recovery for user " << uid;
+ for (auto entry : entries) {
+ const char* type = entry.first.c_str();
+ const char* file = entry.second.c_str();
+ if (!RunBackend(uid, type, file))
+ LOG(ERROR) << "Recovery process for " << file << " failed";
}
}
int main() {
PkgRecoveryService service;
- if (!service.Init()) {
- LOG(ERROR) << "Failed to initialize service";
- return -1;
- }
service.Run();
return 0;
}
+++ /dev/null
-// Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
-// Use of this source code is governed by an apache-2.0 license that can be
-// found in the LICENSE file.
-
-#include <boost/exception/diagnostic_information.hpp>
-#include <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <glib.h>
-#include <gio/gio.h>
-
-#include <tzplatform_config.h>
-#include <manifest_parser/utils/logging.h>
-#include <common/request.h>
-#include <common/utils/user_util.h>
-
-#include <regex>
-#include <string>
-#include <iostream>
-#include <utility>
-#include <vector>
-
-namespace bf = boost::filesystem;
-namespace bs = boost::system;
-namespace ci = common_installer;
-
-namespace {
-
-typedef std::pair<std::string, std::string> RecoverEntry;
-
-const char kRecoveryFilePattern[] = "^(.*)-recovery-(.*)";
-const char kRecoveryMethodName[] = "RecoverPkg";
-const char kDBusServiceName[] = "org.tizen.pkg_recovery";
-const char kDBusObjectPath[] = "/org/tizen/pkg_recovery";
-const char kDBusInterfaceName[] = "org.tizen.pkg_recovery";
-const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
-
-bool RequestRecoveryService(uid_t uid, const char* type, const char* file) {
- GError* err = nullptr;
- GDBusConnection* con = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
- if (!con || err) {
- LOG(WARNING) << "Failed to get dbus connection: " << err->message;
- g_error_free(err);
- return false;
- }
- GDBusProxy* proxy = g_dbus_proxy_new_sync(con, G_DBUS_PROXY_FLAGS_NONE,
- nullptr, kDBusServiceName, kDBusObjectPath, kDBusInterfaceName, nullptr,
- &err);
- if (!proxy) {
- std::string err_msg;
- if (err) {
- err_msg = std::string(err->message);
- g_error_free(err);
- }
- LOG(ERROR) << "Failed to get dbus proxy: " << err_msg;
- g_object_unref(con);
- return false;
- }
- GVariant* r = g_dbus_proxy_call_sync(proxy, kRecoveryMethodName,
- g_variant_new("(uss)", uid, type, file), G_DBUS_CALL_FLAGS_NONE, -1,
- nullptr, &err);
- if (!r) {
- std::string err_msg;
- if (err) {
- err_msg = std::string(err->message);
- g_error_free(err);
- }
- LOG(ERROR) << "Failed to request: " << err_msg;
- g_object_unref(proxy);
- g_object_unref(con);
- return false;
- }
- bool result;
- g_variant_get(r, "(b)", &result);
-
- g_variant_unref(r);
- g_object_unref(proxy);
- g_object_unref(con);
-
- return result;
-}
-
-std::vector<RecoverEntry> SearchRecoveryFiles(uid_t uid) {
- std::vector<RecoverEntry> list;
- const bf::path recovery_dir = ci::GetRootAppPath(false, uid);
- for (bf::directory_iterator iter(recovery_dir);
- iter != bf::directory_iterator();
- ++iter) {
- try {
- std::string file = iter->path().filename().string();
- std::regex recovery_regex(kRecoveryFilePattern);
- std::smatch match;
- if (std::regex_search(file, match, recovery_regex)) {
- LOG(INFO) << "Found recovery file: " << file;
- std::string type(match[1]);
- list.emplace_back(type, iter->path().string());
- }
- } catch (...) {
- LOG(WARNING) << "Exception occurred: "
- << boost::current_exception_diagnostic_information();
- continue;
- }
- }
-
- return list;
-}
-
-} // namespace
-
-int main() {
- uid_t uid = getuid();
- std::vector<std::pair<std::string, std::string>> list;
- try {
- list = SearchRecoveryFiles(uid);
- } catch (...) {
- LOG(WARNING) << "Exception occurred: "
- << boost::current_exception_diagnostic_information();
- return 0;
- }
- for (auto entry : list) {
- if (!RequestRecoveryService(uid, entry.first.c_str(),
- entry.second.c_str()))
- LOG(ERROR) << "Failed to recover installation: " << entry.second;
- }
-
- if (ci::IsAdminUser(uid)) {
- list = SearchRecoveryFiles(kGlobalUserUid);
- for (auto entry : list) {
- if (!RequestRecoveryService(uid, entry.first.c_str(),
- entry.second.c_str()))
- LOG(ERROR) << "Failed to recover installation: " << entry.second;
- }
- }
- return 0;
-}