void add_user_subsession(const int session_uid, const std::string_view subsession_id)
{
try {
- std::string main_dir = get_main_dir_by_user_id(session_uid);
+ fs::path main_path = get_main_dir_by_user_id(session_uid);
- create_main_subdirectory(session_uid, main_dir);
+ create_main_subdirectory(session_uid, main_path);
- std::string subsession_dir = main_dir + "/" + subsession_id.data();
- fs::path subsession_path { subsession_dir };
+ fs::path subsession_path = main_path / subsession_id;
if (fs::exists(subsession_path))
throw std::system_error(EEXIST, std::generic_category(),
"Subsession directory already exists");
- std::string tmp_subsession_dir = std::move(main_dir) + "/" + ".tmpnew" + subsession_id.data();
- fs::path tmp_subsession_path { tmp_subsession_dir };
+ const auto tmp_subsession_path = fs::path(subsession_path)
+ .replace_filename(".tmpnew"s + subsession_path.filename().native());
- fs::create_directory(tmp_subsession_dir);
+ fs::create_directory(tmp_subsession_path);
int system_share_gid = OS::get_gid_from_name(system_share_group);
OS::change_owner_and_group(tmp_subsession_path, session_uid, system_share_gid);
- std::string apps_rw_dir = tmp_subsession_dir + "/apps_rw";
- fs::path apps_rw_path { apps_rw_dir };
- std::string source_dir = "/etc/skel/apps_rw";
- auto const source_dir_len = source_dir.length();
+ const auto apps_rw_path = tmp_subsession_path / "apps_rw";
+ const fs::path source_path = "/etc/skel/apps_rw";
+ auto const source_dir_len = source_path.native().length();
/* N.B. Removing temporary destination directory needs some explanation.
* We need to consider the case of partial copying of subsession data
* don't need to follow their parent dir's inheritance. Our method
* aims to replicate that possibly inconsistent state as-is. */
fs::copy
- ( fs::path{ source_dir }
+ ( source_path
, apps_rw_path
, fs::copy_options::recursive
| fs::copy_options::copy_symlinks
static constexpr fs::perms apps_rw_dir_perms = owner_all
| group_read | group_exec;
- for (auto const& entry : fs::recursive_directory_iterator(source_dir)) {
+ for (auto const& entry : fs::recursive_directory_iterator(source_path)) {
const auto s_path = entry.path();
+ /* Do string manipulation instead of `fs::relative(source_path, entry)`,
+ * because relative() resolves symlinks which gives different behaviour. */
std::string_view tmp_path = s_path.native();
tmp_path.remove_prefix(source_dir_len + 1);
// Last but not least - the `apps_rw` directory itself
OS::change_owner_and_group(apps_rw_path, session_uid, system_share_gid);
fs::permissions(apps_rw_path, apps_rw_dir_perms);
- OS::copy_smack_attributes(source_dir, apps_rw_path);
+ OS::copy_smack_attributes(source_path, apps_rw_path);
// Copy + rename so that the replacement is atomic
fs::rename(tmp_subsession_path, subsession_path);