1 // Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/utils/user_util.h"
7 #include <manifest_parser/utils/logging.h>
10 #include <boost/filesystem/path.hpp>
14 #include <gum/gum-user.h>
15 #include <gum/gum-user-service.h>
16 #include <gum/common/gum-user-types.h>
20 #include "common/utils/glist_range.h"
22 namespace bf = boost::filesystem;
26 const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
27 const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
29 const int kRetryMax = 5;
30 const int kRetryDelay = 1000000 / 2;
34 namespace common_installer {
36 UserList GetUserList() {
37 gchar** user_type_strv = gum_user_type_to_strv(
38 GUM_USERTYPE_ADMIN | GUM_USERTYPE_GUEST | GUM_USERTYPE_NORMAL);
39 GumUserService* service = nullptr;
40 GumUserList* gum_user_list = nullptr;
42 bool is_offline = getuid() == 0;
43 // FIXME: Temporary retry logic, this should be removed
44 while (count < kRetryMax) {
45 service = gum_user_service_create_sync(is_offline ? TRUE : FALSE);
46 if (service == nullptr) {
48 LOG(WARNING) << "Failed to create gum user service!";
52 LOG(WARNING) << "Failed to create gum user service! ("
53 << count << "/" << kRetryMax << ")";
59 gum_user_service_get_user_list_sync(service, user_type_strv);
60 g_object_unref(service);
61 if (gum_user_list == nullptr) {
63 LOG(WARNING) << "Failed to get gum user list!";
67 LOG(WARNING) << "Failed to get gum user list! ("
68 << count << "/" << kRetryMax << ")";
75 if (gum_user_list == nullptr) {
76 g_strfreev(user_type_strv);
81 for (GumUser* guser : GListRange<GumUser*>(gum_user_list)) {
83 g_object_get(G_OBJECT(guser), "uid", &uid, nullptr);
85 g_object_get(G_OBJECT(guser), "gid", &gid, nullptr);
86 gchar* homedir = nullptr;
87 g_object_get(G_OBJECT(guser), "homedir", &homedir, nullptr);
88 if (homedir == nullptr) {
89 LOG(WARNING) << "No homedir for uid: " << uid;
92 list.emplace_back(uid, gid, bf::path(homedir));
95 g_strfreev(user_type_strv);
96 gum_user_service_list_free(gum_user_list);
100 boost::optional<bool> IsAdminUser(uid_t uid) {
103 bool is_offline = getuid() == 0;
105 guser = gum_user_get_sync(uid, is_offline ? TRUE : FALSE);
109 LOG(WARNING) << "Failed to get gum user!";
113 LOG(WARNING) << "Failed to get gum user! ("
114 << count << "/" << kRetryMax << ")";
116 } while (count < kRetryMax);
120 g_object_get(G_OBJECT(guser), "usertype", &ut, NULL);
122 if (ut == GUM_USERTYPE_ADMIN)
126 g_object_unref(guser);
130 boost::optional<gid_t> GetGidByGroupName(const char* groupname) {
131 char buf[kGRBufSize];
134 int ret = getgrnam_r(groupname, &entry, buf, sizeof(buf), &ge);
135 if (ret || ge == nullptr)
140 std::string GetUsernameByUid(uid_t user) {
142 struct passwd* pwd_result;
143 char buf[kPWBufSize];
144 int ret = getpwuid_r(user, &pwd, buf, sizeof(buf), &pwd_result);
145 if (ret != 0 || pwd_result == nullptr)
150 boost::optional<uid_t> GetUidByUserName(const char* username) {
152 struct passwd* pwd_result;
153 char buf[kPWBufSize];
154 int ret = getpwnam_r(username, &pwd, buf, sizeof(buf), &pwd_result);
155 if (ret != 0 || pwd_result == nullptr)
160 boost::optional<gid_t> GetGidByUid(uid_t uid) {
162 struct passwd* pwd_result;
163 char buf[kPWBufSize];
164 int ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
165 if (ret != 0 || pwd_result == nullptr)
170 std::string GetGroupNameByGid(gid_t gid) {
171 char buf[kGRBufSize];
174 int ret = getgrgid_r(gid, &entry, buf, sizeof(buf), &ge);
175 if (ret || ge == nullptr) {
178 return entry.gr_name;
181 std::vector<std::string> GetLightUserList(uid_t uid) {
183 subsession_user_t* user_list = nullptr;
184 int ret = subsession_get_user_list(
185 static_cast<int>(uid), &user_list, &user_count);
186 if (ret != TIZEN_ERROR_NONE) {
187 LOG(ERROR) << "Failed to get light user list : " << ret;
191 std::vector<std::string> result_list;
192 for (int i = 0; i < user_count; i++) {
193 if (strlen(user_list[i]) == 0)
196 result_list.emplace_back(user_list[i]);
199 std::free(user_list);
203 } // namespace common_installer