Add file system helper functions needed by the service 00/272800/15
authorAdam Michalski <a.michalski2@partner.samsung.com>
Thu, 24 Mar 2022 17:35:10 +0000 (18:35 +0100)
committerAdam Michalski <a.michalski2@partner.samsung.com>
Thu, 7 Apr 2022 12:16:23 +0000 (14:16 +0200)
File system helpers that are going to be used by the AddUser and RemoveUser calls.

Change-Id: Ib392c6630172bb69552b6480072139d1ad985643

sessiond/CMakeLists.txt
sessiond/src/fs_helpers.cpp [new file with mode: 0644]
sessiond/src/fs_helpers.h [new file with mode: 0644]

index 8fc93a25e1bfb6fbbd552e4287ab6075857253ba..fedf81201cdc0b5d905d2bb03fc2ed44d9b404ee 100644 (file)
@@ -4,6 +4,7 @@ pkg_check_modules(DEPS REQUIRED IMPORTED_TARGET gio-2.0)
 set(
        sessiond_SRCS
        src/main.cpp
+       src/fs_helpers.cpp
 )
 add_executable(sessiond ${sessiond_SRCS})
 target_compile_features(sessiond PUBLIC cxx_std_20)
diff --git a/sessiond/src/fs_helpers.cpp b/sessiond/src/fs_helpers.cpp
new file mode 100644 (file)
index 0000000..59d9f2f
--- /dev/null
@@ -0,0 +1,121 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE. */
+
+#include <pwd.h>
+#include <unistd.h>
+#include <filesystem>
+#include <iostream>
+#include <string>
+#include "fs_helpers.h"
+
+namespace fs = std::filesystem;
+
+std::string fs_helpers::get_home_dir_by_user_id(const int uid)
+{
+       auto max_buf_size = static_cast<ssize_t>(sysconf(_SC_GETPW_R_SIZE_MAX));
+       std::system_error err(std::error_code()
+               , "Couldn't get home directory for session_uid=" + std::to_string(uid));
+
+       if (max_buf_size <= 0)
+               throw err;
+
+       std::unique_ptr<char[]> str_buf(new char[max_buf_size]);
+       // N.B. `new` throws `std::bad_alloc` exception if it runs out of memory,
+       // so there's no need to check if it's successful here
+
+       passwd pass_buf, *pass_ptr;
+       getpwuid_r(uid, &pass_buf, str_buf.get(), max_buf_size, &pass_ptr);
+
+       if (!pass_ptr)
+               throw err;
+
+       return std::string(pass_ptr->pw_dir);
+}
+
+void fs_helpers::add_user_subsession(const int session_uid, const int subsession_id)
+{
+       std::system_error add_ex(std::error_code(), "Couldn't add user subsession data");
+       try {
+               std::string home_dir = get_home_dir_by_user_id(session_uid);
+               std::string subsession_dir = std::move(home_dir) + "/subsessions/" + std::to_string(subsession_id);
+               fs::path subsession_path { subsession_dir };
+
+               if (fs::exists(subsession_path))
+                       throw add_ex;
+
+               fs::path subsession_tmp_path { std::move(subsession_dir) + ".tmpnew" };
+               fs::copy
+                       ( fs::path{ "/etc/skel" }
+                       , subsession_tmp_path
+                       , fs::copy_options::recursive
+               );
+
+               // Copy + rename so that the replacement is atomic
+               fs::rename(subsession_tmp_path, subsession_path);
+
+               // TODO: chown/chmod of the copied files & directories
+               // TODO: copy/set SMACK attributes
+       }
+       catch (fs::filesystem_error const &ex) {
+               std::cerr << "Exception " << ex.what() << std::endl
+                       << "while copying user subsession data [session_uid=" << session_uid
+                       << " subsession_id=" << subsession_id << "]" << std::endl;
+               throw add_ex;
+       }
+       catch (std::exception const &ex) {
+               std::cerr << "Exception " << ex.what() << std::endl
+                       << "when invoking fs_helpers::get_home_dir_by_user_id() "
+                       << "while copying user subsession data [session_uid=" << session_uid
+                       << " subsession_id=" << subsession_id << "]" << std::endl;
+               throw add_ex;
+       }
+}
+
+void fs_helpers::remove_user_subsession(const int session_uid, const int subsession_id)
+{
+       std::system_error remove_ex(std::error_code(), "Couldn't remove user subsession data");
+       try {
+               std::string home_dir = get_home_dir_by_user_id(session_uid);
+               fs::path subsession_path {
+                       std::move(home_dir) + "/subsessions/" + std::to_string(subsession_id)
+               };
+
+               if (!fs::exists(subsession_path))
+                       throw remove_ex;
+
+               fs::remove_all(subsession_path);
+       }
+       catch (fs::filesystem_error const &ex) {
+               std::cerr << "Exception " << ex.what() << std::endl
+                       << "while deleting user subsession data [session_uid=" << session_uid
+                       << " subsession_id=" << subsession_id << "]" << std::endl;
+               throw remove_ex;
+       }
+       catch (std::exception const &ex) {
+               std::cerr << "Exception " << ex.what() << std::endl
+                       << "when invoking fs_helpers::get_home_dir_by_user_id() "
+                       << "while removing user subsession data [session_uid=" << session_uid
+                       << " subsession_id=" << subsession_id << "]" << std::endl;
+               throw remove_ex;
+       }
+}
+
diff --git a/sessiond/src/fs_helpers.h b/sessiond/src/fs_helpers.h
new file mode 100644 (file)
index 0000000..bc573dc
--- /dev/null
@@ -0,0 +1,10 @@
+#pragma once
+#include <string>
+
+namespace fs_helpers
+{
+       std::string get_home_dir_by_user_id(const int uid);
+       void    add_user_subsession(const int session_uid, const int subsession_id);
+       void remove_user_subsession(const int session_uid, const int subsession_id);
+}
+