objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: AddUser
- parameters: (ii)
+ parameters: (is)
session_uid <int32> in
- subsession_id <int32> in
+ subsession_id <string> in
2. Remove a user from the subsession:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: RemoveUser
- parameters: (ii)
+ parameters: (is)
session_uid <int32> in
- subsession_id <int32> in
+ subsession_id <string> in
3. Switch the subsession user:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: SwitchUser
- parameters: (iii)
+ parameters: (is)
session_uid <int32> in
- next_subsession_id <int32> in
+ next_subsession_id <string> in
4. Register to wait for user add operation:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: AddUserDone
- parameters: (ii)
+ parameters: (is)
session_uid <int32> in
- subsession_id <int32> in
+ subsession_id <string> in
8. Mark user remove callback as done:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: RemoveUserDone
- parameters: (ii)
+ parameters: (is)
session_uid <int32> in
- subsession_id <int32> in
+ subsession_id <string> in
9. Mark user switch callback as done:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: GetUserList
- parameters: (i) -> (ai)
+ parameters: (i) -> (as)
session_uid <int32> in
- subsession_id_list <array<int32>> out
+ subsession_id_list <array<string>> out
# Signals
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: AddUserStarted
- parameters: (ii)
+ parameters: (is)
session_uid <int32>
- subsession_id <int32>
+ subsession_id <string>
2. On user removal:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: RemoveUserStarted
- parameters: (ii)
+ parameters: (is)
session_uid <int32>
- subsession_id <int32>
+ subsession_id <string>
3. On user switch:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: SwitchUserStarted
- parameters: (ixii)
+ parameters: (ixss)
session_uid <int32>
switch_id <int64>
- prev_subsession_id <int32>
- next_subsession_id <int32>
+ prev_subsession_id <string>
+ next_subsession_id <string>
4. On user add completed:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: AddUserCompleted
- parameters: (ii)
+ parameters: (is)
session_uid <int32>
- subsession_id <int32>
+ subsession_id <string>
5. On user removal completed:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: RemoveUserCompleted
- parameters: (ii)
+ parameters: (is)
session_uid <int32>
- subsession_id <int32>
+ subsession_id <string>
6. On user switch completed:
objpath: /org/tizen/sessiond
interface: org.tizen.sessiond.subsession.Manager
member: SwitchUserCompleted
- parameters: (ixii)
+ parameters: (ixss)
session_uid <int32>
switch_id <int64>
- prev_subsession_id <int32>
- next_subsession_id <int32>
+ prev_subsession_id <string>
+ next_subsession_id <string>
+ "` subdirectory");
}
-bool fs_helpers::subsession_exists(const int session_uid, const int subsession_id) try {
+bool fs_helpers::subsession_exists(const int session_uid, const std::string_view subsession_id) try {
std::string home_dir = fs_helpers::get_home_dir_by_user_id(session_uid);
std::string main_dir = std::move(home_dir) + "/" + main_dir_name.data();
- std::string subsession_dir = std::move(main_dir) + "/" + std::to_string(subsession_id);
+ std::string subsession_dir = std::move(main_dir) + "/" + subsession_id.data();
fs::path subsession_path { subsession_dir };
return fs::exists(subsession_path);
}
return false;
}
-void fs_helpers::add_user_subsession(const int session_uid, const int subsession_id)
+void fs_helpers::add_user_subsession(const int session_uid, const std::string_view subsession_id)
{
try {
std::string home_dir = get_home_dir_by_user_id(session_uid);
create_main_subdirectory(session_uid, main_dir);
- std::string subsession_dir = std::move(main_dir) + "/" + std::to_string(subsession_id);
+ std::string subsession_dir = main_dir + "/" + subsession_id.data();
fs::path subsession_path { subsession_dir };
if (fs::exists(subsession_path))
throw std::system_error(EEXIST, std::generic_category(),
"Subsession directory already exists");
- fs::create_directory(subsession_dir);
+ std::string tmp_subsession_dir = std::move(main_dir) + "/" + ".tmpnew" + subsession_id.data();
+ fs::path tmp_subsession_path { tmp_subsession_dir };
- std::string apps_rw_dir = subsession_dir + "/apps_rw";
+ fs::create_directory(tmp_subsession_dir);
+
+ std::string apps_rw_dir = tmp_subsession_dir + "/apps_rw";
fs::path apps_rw_path { apps_rw_dir };
- std::string apps_rw_tmp_dir = apps_rw_dir + ".tmpnew";
- fs::path apps_rw_tmp_path { apps_rw_tmp_dir };
std::string source_dir = "/etc/skel/apps_rw";
auto const source_dir_len = source_dir.length();
fs::copy
( fs::path{ source_dir }
- , apps_rw_tmp_path
+ , apps_rw_path
, fs::copy_options::recursive
| fs::copy_options::copy_symlinks
);
std::string tmp_path = s_path;
tmp_path.erase(0, source_dir_len);
- std::string d_path = apps_rw_tmp_dir + std::move(tmp_path);
+ std::string d_path = apps_rw_dir + std::move(tmp_path);
copy_ownership(s_path, d_path);
copy_smack_attributes(s_path, d_path);
}
// Last but not least - the `apps_rw` directory itself
- copy_ownership(source_dir, apps_rw_tmp_dir);
- copy_smack_attributes(source_dir, apps_rw_tmp_dir);
+ copy_ownership(source_dir, apps_rw_dir);
+ copy_smack_attributes(source_dir, apps_rw_dir);
// Copy + rename so that the replacement is atomic
- fs::rename(apps_rw_tmp_path, apps_rw_path);
+ fs::rename(tmp_subsession_path, subsession_path);
}
catch (std::system_error const &ex) {
}
}
-void fs_helpers::remove_user_subsession(const int session_uid, const int subsession_id)
+void fs_helpers::remove_user_subsession(const int session_uid, const std::string_view subsession_id)
{
try {
std::string home_dir = get_home_dir_by_user_id(session_uid);
fs::path subsession_path {
- std::move(home_dir) + "/" + main_dir_name.data() + "/" + std::to_string(subsession_id)
+ std::move(home_dir) + "/" + main_dir_name.data() + "/" + subsession_id.data()
};
if (!fs::exists(subsession_path))
};
}
-std::vector<int> fs_helpers::get_user_list(const int session_uid) try
+std::vector<std::string> fs_helpers::get_user_list(const int session_uid) try
{
auto const subsession_path = get_subsession_dir_by_uid(session_uid);
- std::vector<int> subsessions;
+ std::vector<std::string> subsessions;
/* NB: the `subsession` folder may not exist if no
* subsessions have been created before. */
if (!fs::is_directory(entry.status()))
continue;
- std::string_view s_path = entry.path().filename().native();
-
- /* NB: the std::stoi check below is insufficient,
- * since you can create folders named +123 or 0x123. */
- if (s_path.find_first_not_of("0123456789") != std::string::npos)
- continue;
+ const auto s_path = entry.path().filename();
- try {
- const int subsession_id { std::stoi(s_path.data()) };
- if (subsession_id > 0)
- subsessions.emplace_back(subsession_id);
- }
- catch (std::exception const &ex) {
- continue;
- }
+ if (check_subsession_id_valid(s_path.native()))
+ subsessions.emplace_back(s_path);
}
return subsessions;
#include "tuple_hash.hpp"
#include "wait_manager.hpp"
-#include "sessiond-internal.h"
-
static constexpr const char * get_dbus_error_mapping (subsession_error_e subsession_error)
{
/* I want this function to be evaluated at compile time
};
struct sessiond_context {
- /* A special value representing the state
- * before any sub session is switched to. */
- static constexpr int INITIAL_SUB_SESSION_ID = 0;
-
sessiond_context() : data(xml), id(), loop()
{
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL);
throw std::runtime_error("Bus name lost");
}
- bool check_parameters_invalid(GDBusMethodInvocation *invocation, const int session_uid, const int subsession_id)
+ bool check_parameters_invalid(GDBusMethodInvocation *invocation,
+ const int session_uid, const std::string_view subsession_id)
{
if (session_uid <= 0) {
g_dbus_method_invocation_return_dbus_error(invocation,
get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
return true;
}
- if (subsession_id <= 0) {
+
+ if (!check_subsession_id_valid(subsession_id)) {
g_dbus_method_invocation_return_dbus_error(invocation,
- get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative subsession_id passed");
+ get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Incorrect subsession_id passed");
return true;
}
void on_add_user(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
- auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
+ auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, std::string>(parameters);
if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
void on_remove_user(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
- auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
+ auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, std::string>(parameters);
if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
- int current_subsession_id = INITIAL_SUB_SESSION_ID;
+ std::string_view current_subsession_id = SUBSESSION_INITIAL_SID;
if (last_subsession_per_session.contains(session_uid))
current_subsession_id = last_subsession_per_session.at(session_uid);
if (subsession_id == current_subsession_id) {
void on_switch_user(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
- auto [ session_uid, next_subsession_id ] = tuple_from_g_variant<int, int>(parameters);
+ auto [ session_uid, next_subsession_id ] = tuple_from_g_variant<int, std::string>(parameters);
if (session_uid <= 0) {
g_dbus_method_invocation_return_dbus_error(invocation,
get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative UID passed");
return;
}
- // N.B. Switch to user '0' is possible and it means no subsession is currently active
- if (next_subsession_id < 0) {
+
+ // N.B. Switch to user "" (empty string) is possible and it means no subsession is currently active
+ if (next_subsession_id != SUBSESSION_INITIAL_SID && !check_subsession_id_valid(next_subsession_id)) {
g_dbus_method_invocation_return_dbus_error(invocation,
- get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Negative subsession_id passed");
+ get_dbus_error_mapping(SUBSESSION_ERROR_INVALID_PARAMETER), "Incorrect subsession_id passed");
return;
}
-
- if (next_subsession_id > 0 && !fs_helpers::subsession_exists(session_uid, next_subsession_id)) {
+ if (next_subsession_id != SUBSESSION_INITIAL_SID && !fs_helpers::subsession_exists(session_uid, next_subsession_id)) {
g_dbus_method_invocation_return_dbus_error(invocation,
get_dbus_error_mapping(SUBSESSION_ERROR_NOT_AVAILABLE), "Subsession does not exist");
return;
switch_id += 1;
- int prev_subsession_id = INITIAL_SUB_SESSION_ID;
+ std::string_view prev_subsession_id = SUBSESSION_INITIAL_SID;
if (last_subsession_per_session.contains(session_uid))
prev_subsession_id = last_subsession_per_session.at(session_uid);
last_subsession_per_session[session_uid] = next_subsession_id;
wait_switch.try_emplace(session_uid, session_uid, connection, "SwitchUserCompleted");
- wait_switch.at(session_uid).on_start(switch_id, { prev_subsession_id, next_subsession_id });
+ wait_switch.at(session_uid).on_start(switch_id, { std::string(prev_subsession_id), next_subsession_id });
g_dbus_method_invocation_return_value(invocation, nullptr);
}
void on_add_user_done(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
- auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
+ auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, std::string>(parameters);
if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
void on_remove_user_done(GDBusMethodInvocation *invocation, std::string_view sender, GVariant *parameters)
{
- auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, int>(parameters);
+ auto [ session_uid, subsession_id ] = tuple_from_g_variant<int, std::string>(parameters);
if (check_parameters_invalid(invocation, session_uid, subsession_id))
return;
auto users = fs_helpers::get_user_list(session_uid);
// TODO: It would be cool to be able to use vals_to_g_variant here.
- g_autoptr(GVariantBuilder) builder = g_variant_builder_new(G_VARIANT_TYPE("ai"));
- for (auto user : users)
- g_variant_builder_add(builder, "i", user);
- auto ret = g_variant_new("(ai)", builder);
+ g_autoptr(GVariantBuilder) builder = g_variant_builder_new(G_VARIANT_TYPE("as"));
+ for (const auto &user : users)
+ g_variant_builder_add(builder, "s", user.c_str());
+ auto ret = g_variant_new("(as)", builder);
g_dbus_method_invocation_return_value(invocation, ret);
}
return;
}
- int subsession_id = INITIAL_SUB_SESSION_ID;
+ std::string subsession_id = SUBSESSION_INITIAL_SID;
if (last_subsession_per_session.contains(session_uid))
subsession_id = last_subsession_per_session.at(session_uid);
"<interface name=\"org.tizen.sessiond.subsession.Manager\">"
"<method name=\"AddUser\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"in\"/>"
"</method>"
"<method name=\"RemoveUser\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"in\"/>"
"</method>"
"<method name=\"SwitchUser\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"next_subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"next_subsession_id\" type=\"s\" direction=\"in\"/>"
"</method>"
"<method name=\"AddUserWait\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
"</method>"
"<method name=\"AddUserDone\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"in\"/>"
"</method>"
"<method name=\"RemoveUserDone\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"in\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"in\"/>"
"</method>"
"<method name=\"SwitchUserDone\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
"</method>"
"<method name=\"GetUserList\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id_list\" type=\"ai\" direction=\"out\"/>"
+ "<arg name=\"subsession_id_list\" type=\"as\" direction=\"out\"/>"
"</method>"
"<method name=\"GetCurrentUser\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"in\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"out\"/>"
"</method>"
"<signal name=\"AddUserStarted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"<signal name=\"RemoveUserStarted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"<signal name=\"SwitchUserStarted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
"<arg name=\"switch_id\" type=\"x\" direction=\"out\"/>"
- "<arg name=\"prev_subsession_id\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"next_subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"prev_subsession_id\" type=\"s\" direction=\"out\"/>"
+ "<arg name=\"next_subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"<signal name=\"AddUserCompleted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"<signal name=\"RemoveUserCompleted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"<signal name=\"SwitchUserCompleted\">"
"<arg name=\"session_uid\" type=\"i\" direction=\"out\"/>"
"<arg name=\"switch_id\" type=\"x\" direction=\"out\"/>"
- "<arg name=\"prev_subsession_id\" type=\"i\" direction=\"out\"/>"
- "<arg name=\"next_subsession_id\" type=\"i\" direction=\"out\"/>"
+ "<arg name=\"prev_subsession_id\" type=\"s\" direction=\"out\"/>"
+ "<arg name=\"next_subsession_id\" type=\"s\" direction=\"out\"/>"
"</signal>"
"</interface>"
"</node>";
// Consider simplifying wait_manager.
// N.B. Although GLib is multi-threaded, the following data structures do not need
// to be protected by mutexes as all of them are accessed from DBus handlers only.
- std::unordered_map<int, wait_manager<std::tuple<int>, std::tuple<>>> wait_add;
- std::unordered_map<int, wait_manager<std::tuple<int>, std::tuple<>>> wait_remove;
- std::unordered_map<int, wait_manager<std::tuple<uint64_t>, std::tuple<int, int>>> wait_switch;
+ std::unordered_map<int, wait_manager<std::tuple<std::string>, std::tuple<>>> wait_add;
+ std::unordered_map<int, wait_manager<std::tuple<std::string>, std::tuple<>>> wait_remove;
+ std::unordered_map<int, wait_manager<std::tuple<uint64_t>, std::tuple<std::string, std::string>>> wait_switch;
// used for tracking subsession switches for each `session_uid`
- std::unordered_map<int, int> last_subsession_per_session;
+ std::unordered_map<int, std::string> last_subsession_per_session;
uint64_t switch_id = 0;