Extract AddSession dir helpers to dir backend. 54/320154/5
authorMichal Bloch <m.bloch@samsung.com>
Fri, 21 Feb 2025 18:42:25 +0000 (19:42 +0100)
committerMichal Bloch <m.bloch@samsung.com>
Thu, 27 Feb 2025 15:28:12 +0000 (16:28 +0100)
Change-Id: I0aa9ca022542cb6966911cc45b800110c37b11ff
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
src/service/src/dir_backend.hpp
src/service/src/dir_backend_regular_dir.cpp
src/service/src/dir_backend_regular_dir.hpp
src/service/src/fs_helpers.cpp
src/service/src/fs_helpers.hpp
src/service/src/main.cpp

index ce9b8d6c7810d54baca0308c276e509bb5e83841..069af618f59b9c186a8b03946651273ff4e61ddb 100644 (file)
@@ -2,8 +2,15 @@
 
 #include <filesystem>
 
+namespace fs = std::filesystem;
+
 struct DirBackend {
        virtual void RemoveSubsession (const std::filesystem::path& subsession_path) const = 0;
        virtual void SwitchSubsessionAway (const std::filesystem::path& subsession_path) const = 0;
        virtual void SwitchSubsessionInto (const std::filesystem::path& subsession_path) const = 0;
 };
+
+struct DirBackendAdd {
+       virtual fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const = 0;
+       virtual void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path) const = 0;
+};
index 39db809cdc39dd80bc7422de9b7abd16a1c5b3da..be9e7d551cc78ff4d15992f1f65d2f99ad1342d6 100644 (file)
  * THE SOFTWARE. */
 
 #include "dir_backend_regular_dir.hpp"
+#include "os_ops.hpp"
 
 namespace fs = std::filesystem;
 using namespace std::string_literals;
 
+fs::path DirBackendAddRegularDir::AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const
+{
+       auto tmp_subsession_path = subsession_path;
+       tmp_subsession_path.replace_filename(".tmpnew"s + subsession_path.filename().native());
+
+       fs::create_directory(tmp_subsession_path);
+       OS::change_owner_and_group(tmp_subsession_path, uid, gid);
+
+       return tmp_subsession_path;
+}
+
+void DirBackendAddRegularDir::AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path) const
+{
+       fs::rename(tmpdir_path, subsession_path);
+}
+
 void DirBackendRegularDir::RemoveSubsession (const fs::path& subsession_path) const
 {
        /* We are going to rename the subsession dir before deleting it,
index 39c49df2d66c59586ac64a65a5e4fc98e576f605..3a7d13022278468612142e384d8867e47a2c5ea4 100644 (file)
@@ -7,3 +7,8 @@ struct DirBackendRegularDir : public DirBackend {
        void SwitchSubsessionAway (const std::filesystem::path& subsession_path) const override;
        void SwitchSubsessionInto (const std::filesystem::path& subsession_path) const override;
 };
+
+struct DirBackendAddRegularDir : public DirBackendAdd {
+       fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
+       void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
+};
index 138370e6f4fb2b6f3349ea0d2f8dff6420cd692c..fe732d5d7b11ad3cc09fe5087ab65234ef0e163f 100644 (file)
@@ -127,7 +127,7 @@ static Directory_Class get_directory_type(std::string_view path)
        return Directory_Class::Users;
 }
 
-void add_user_subsession(const int session_uid, const std::string_view subsession_id)
+void add_user_subsession(const int session_uid, const std::string_view subsession_id, const DirBackendAdd &backend)
 {
        try {
                fs::path main_path = get_main_dir_by_user_id(session_uid);
@@ -140,13 +140,13 @@ void add_user_subsession(const int session_uid, const std::string_view subsessio
                        throw std::system_error(EEXIST, std::generic_category(),
                                "Subsession directory already exists");
 
-               auto tmp_subsession_path = fs::path(subsession_path);
-               tmp_subsession_path.replace_filename(".tmpnew"s + subsession_path.filename().native());
+               const int system_share_gid = OS::get_gid_from_name(system_share_group);
 
-               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);
+               // Work off a temporary dir and then switch it at once so that it appears atomically
+               const auto tmp_subsession_path = backend.AddSubsessionPrepare
+                       ( subsession_path
+                       , session_uid, system_share_gid
+               );
 
                const auto apps_rw_path = tmp_subsession_path / "apps_rw";
                const fs::path source_path = "/etc/skel/apps_rw";
@@ -232,9 +232,7 @@ void add_user_subsession(const int session_uid, const std::string_view subsessio
                fs::permissions(apps_rw_path, apps_rw_dir_perms);
                OS::copy_smack_attributes(source_path, apps_rw_path);
 
-               // Copy + rename so that the replacement is atomic
-               fs::rename(tmp_subsession_path, subsession_path);
-
+               backend.AddSubsessionFinalize(tmp_subsession_path, subsession_path);
        }
        catch (std::system_error const &ex) {
                LOGE("Logic exception %s\nwhile copying user subsession data [session_uid=%d subsession_id=%s]", ex.what(), session_uid, subsession_id.data());
index acdc7838086a9a085b5e90ceefaa745be56741d3..d502168a99699953fca57afb47a78aeff3576f34 100644 (file)
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "dir_backend.hpp"
+
 #include <sys/smack.h>
 #include <filesystem>
 #include <string>
@@ -7,7 +9,7 @@
 #include <vector>
 
 bool subsession_exists(const int session_uid, const std::string_view subsession_id);
-void add_user_subsession(const int session_uid, const std::string_view subsession_id);
+void add_user_subsession(const int session_uid, const std::string_view subsession_id, const DirBackendAdd& backend);
 void remove_user_subsession(const int session_uid, const std::string_view subsession_id);
 bool switch_user_subsession(const int session_uid, const std::string_view prev_subsession, const std::string_view next_subsession);
 std::vector<std::string> get_user_list(const int session_uid);
index 7b03c8d82e3690d5418f36b218b6ffc2f6c67c46..9ab65ae295b33eed74b473017070424db8c000a8 100644 (file)
@@ -35,6 +35,7 @@
 #include "tuple_g_variant_helpers.hpp"
 #include "tuple_hash.hpp"
 #include "wait_manager.hpp"
+#include "dir_backend_regular_dir.hpp"
 
 static constexpr const char * get_dbus_error_mapping (subsession_error_e subsession_error)
 {
@@ -175,7 +176,7 @@ struct sessiond_context {
                                vals_to_g_variant(session_uid, subsession_id), &err))
                        g_error_throw(err, "Failed to emit a signal: ");
 
-               add_user_subsession(session_uid, subsession_id);
+               add_user_subsession(session_uid, subsession_id, DirBackendAddRegularDir {});
 
                wait_add.try_emplace(session_uid, session_uid, connection, "AddUserCompleted");
                wait_add.at(session_uid).on_start(subsession_id, { });