/*
* @file temp_test_user.cpp
* @author Jan Cybulski (j.cybulski@partner.samsung.com)
+ * @author Rafal Krypa (j.cybulski@samsung.com)
* @version 1.0
* @brief File with class for users management
*/
+#include <memory.h>
+#include <tests_common.h>
#include <temp_test_user.h>
#include <glib-object.h>
#include <dpl/test/test_runner.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
void TemporaryTestUser::create(void)
{
- if (m_guser) {
+ if (m_uid != 0)
remove();
- };
-
- m_guser = gum_user_create_sync (m_offline);
- RUNNER_ASSERT_MSG(m_guser != nullptr, "Failed to create gumd user object");
- g_object_set(G_OBJECT(m_guser), "usertype", m_userType, NULL);
- g_object_set(G_OBJECT(m_guser), "username", m_userName.c_str(), NULL);
- gboolean added = gum_user_add_sync(m_guser);
- RUNNER_ASSERT_MSG(added, "Failed to add user");
- g_object_get(G_OBJECT(m_guser), "uid", &m_uid, NULL);
+
+ bool ret = m_runner.userCreate(m_userName, m_userType, m_offline, m_uid, m_gid);
+ RUNNER_ASSERT_MSG(ret, "Failed to add user");
RUNNER_ASSERT_MSG(m_uid != 0, "Something strange happened during user creation. uid == 0.");
- g_object_get(G_OBJECT(m_guser), "gid", &m_gid, NULL);
RUNNER_ASSERT_MSG(m_gid != 0, "Something strange happened during user creation. gid == 0.");
}
void TemporaryTestUser::remove(void)
{
- if(m_guser){
- gum_user_delete_sync(m_guser, TRUE);
- g_object_unref(m_guser);
- m_guser = nullptr;
- }
+ if (m_uid == 0)
+ return;
+
+ m_runner.userRemove(m_uid, m_offline);
+ m_uid = m_gid = 0;
}
TemporaryTestUser::~TemporaryTestUser()
{
this->remove();
}
+
+TemporaryTestUser::GumdRunner TemporaryTestUser::m_runner = TemporaryTestUser::GumdRunner();
+
+TemporaryTestUser::GumdRunner::GumdRunner()
+{
+ int sock[2];
+ int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ RUNNER_ASSERT_MSG(ret != -1, "socketpair() failed");
+
+ pid_t pid = fork();
+ RUNNER_ASSERT_MSG(pid != -1, "fork() failed");
+ if (pid) { // parent
+ m_sock = sock[0];
+ close(sock[1]);
+ return;
+ } else { // child
+ m_sock = sock[1];
+ close(sock[0]);
+ prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // Don't outlive parent process
+ run(); // Never returns
+ }
+}
+
+TemporaryTestUser::GumdRunner::~GumdRunner()
+{
+ close(m_sock);
+}
+
+bool TemporaryTestUser::GumdRunner::userCreate(std::string userName,
+ GumUserType userType, bool offline, uid_t &uid, gid_t &gid)
+{
+ put(static_cast<int>(opType::USER_CREATE));
+ put(userName.size());
+ put(userName.c_str(), userName.size());
+ put(userType);
+ put(offline);
+
+ bool ret = get<bool>();
+ if (ret) {
+ uid = get<uid_t>();
+ gid = get<gid_t>();
+ }
+ return ret;
+}
+
+bool TemporaryTestUser::GumdRunner::userRemove(uid_t uid, bool offline)
+{
+ put(static_cast<int>(opType::USER_REMOVE));
+ put(uid);
+ put(offline);
+ return get<bool>();
+}
+
+
+void TemporaryTestUser::GumdRunner::run()
+{
+ DEFINE_SMARTPTR(g_object_unref, GumUser, GumUserPtr);
+
+ while (true) {
+ switch(static_cast<opType>(get<int>())) {
+ case opType::USER_CREATE:
+ {
+ size_t userNameLen = get<size_t>();
+ std::unique_ptr<char[]> userNamePtr(new char[userNameLen + 1]);
+ get(userNamePtr.get(), userNameLen);
+ userNamePtr[userNameLen] = '\0';
+ GumUserType userType = get<GumUserType>();
+ bool offline = get<bool>();
+
+ bool result = false;
+ uid_t uid;
+ gid_t gid;
+
+ GumUserPtr userPtr(gum_user_create_sync(offline));
+ if (userPtr) {
+ g_object_set(G_OBJECT(userPtr.get()),
+ "username", userNamePtr.get(),
+ "usertype", userType,
+ nullptr);
+ gboolean ret = gum_user_add_sync(userPtr.get());
+ if (ret == TRUE) {
+ g_object_get(G_OBJECT(userPtr.get()), "uid", &uid, nullptr);
+ g_object_get(G_OBJECT(userPtr.get()), "gid", &gid, nullptr);
+ result = true;
+ }
+ }
+
+ put(result);
+ if (result) {
+ put(uid);
+ put(gid);
+ }
+ }
+ break;
+
+ case opType::USER_REMOVE:
+ {
+ uid_t uid = get<uid_t>();
+ bool offline = get<bool>();
+ bool result = false;
+
+ GumUserPtr userPtr(gum_user_get_sync(uid, offline));
+ if (userPtr) {
+ gboolean ret = gum_user_delete_sync(userPtr.get(), TRUE);
+ result = (ret == TRUE);
+ }
+ put(static_cast<bool>(result));
+ }
+ break;
+ }
+ }
+}
+
+void TemporaryTestUser::GumdRunner::get(void *buf, size_t cnt)
+{
+ int ret;
+ for (size_t pos = 0; pos < cnt; pos += ret) {
+ ret = TEMP_FAILURE_RETRY(
+ read(m_sock, static_cast<char *>(buf) + pos, cnt - pos));
+ RUNNER_ASSERT_MSG(ret != -1, "read() failed");
+ }
+}
+
+void TemporaryTestUser::GumdRunner::put(const void *buf, size_t cnt)
+{
+ int ret;
+ for (size_t pos = 0; pos < cnt; pos += ret) {
+ ret = TEMP_FAILURE_RETRY(
+ write(m_sock, static_cast<const char *>(buf) + pos, cnt - pos));
+ RUNNER_ASSERT_MSG(ret != -1, "write() failed");
+ }
+}
+
+template<typename T>
+T TemporaryTestUser::GumdRunner::get()
+{
+ T x;
+ get(&x, sizeof(x));
+ return std::move(x);
+}
+
+template<typename T>
+void TemporaryTestUser::GumdRunner::put(const T x)
+{
+ put(&x, sizeof(x));
+}