Add user utils 89/86689/7
authorPiotr Ganicz <p.ganicz@samsung.com>
Thu, 1 Sep 2016 08:16:16 +0000 (10:16 +0200)
committerPiotr Ganicz <p.ganicz@samsung.com>
Tue, 6 Sep 2016 10:28:55 +0000 (12:28 +0200)
This patch gathers the common user functions in one header
and exposes comfortable API for getting uid, useraname,
gid, group name.

Change-Id: I740626455a7dea93af076632fb2fd1216db84b49

src/common/CMakeLists.txt
src/common/paths.cc
src/common/shared_dirs.cc
src/common/step/filesystem/step_acquire_external_storage.cc
src/common/step/filesystem/step_change_owner.cc
src/common/step/filesystem/step_optional_acquire_external_storage.cc
src/common/utils/user_util.cc [new file with mode: 0644]
src/common/utils/user_util.h [new file with mode: 0644]

index b53ea75..c8c0aef 100644 (file)
@@ -98,6 +98,7 @@ SET(SRCS
   tzip_interface.cc
   utils/base64.cc
   utils/file_util.cc
+  utils/user_util.cc
   utils/subprocess.cc
 )
 # Target - definition
index aa9720f..4c55b89 100644 (file)
 #include <tzplatform_config.h>
 #include <storage-internal.h>
 
+#include "common/utils/user_util.h"
+
 namespace bf = boost::filesystem;
+namespace ci = common_installer;
 
 namespace {
 
@@ -46,16 +49,6 @@ boost::filesystem::path GetBackupPath(
   return backup_path;
 }
 
-std::string GetUserNameForUID(uid_t uid) {
-  struct passwd pwd;
-  struct passwd *pwd_result;
-  char buf[kPWBufSize];
-  int ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr)
-    return {};
-  return pwd.pw_name;
-}
-
 }  // namespace
 
 namespace common_installer {
@@ -105,7 +98,7 @@ boost::filesystem::path GetExternalTepPath(RequestMode request_mode,
     return result;
   result = ext_mount_path / "tep";
   if (request_mode == RequestMode::USER)
-    result /= GetUserNameForUID(uid);
+    result /= ci::GetUsernameByUid(uid);
   return result;
 }
 
index ba8ee8c..b4c56dd 100644 (file)
 #include <gio/gio.h>
 #include <vcore/Certificate.h>
 #include <pkgmgr-info.h>
-#include <pwd.h>
-#include <grp.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <tzplatform_config.h>
 #include <sys/xattr.h>
-#include <gum/gum-user.h>
-#include <gum/gum-user-service.h>
-#include <gum/common/gum-user-types.h>
+
 
 #include <algorithm>
 #include <cassert>
@@ -44,6 +40,7 @@
 #include "common/pkgmgr_query.h"
 #include "common/utils/base64.h"
 #include "common/utils/file_util.h"
+#include "common/utils/user_util.h"
 #include "common/utils/glist_range.h"
 
 namespace bf = boost::filesystem;
@@ -56,7 +53,6 @@ namespace {
 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
 const utils::VersionNumber ver30("3.0");
 
-typedef std::vector<std::tuple<uid_t, gid_t, bf::path>> user_list;
 const std::vector<const char*> kEntries = {
   {"/"},
   {"cache/"},
@@ -77,9 +73,6 @@ const char kSkelAppDir[] = "/etc/skel/apps_rw";
 const char kExternalStoragePrivilege[] =
     "http://tizen.org/privilege/externalstorage.appdata";
 
-const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
-const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
-
 bool SetFileOwner(const bf::path& subpath, uid_t uid, gid_t gid) {
   bs::error_code error;
   int fd = open(subpath.c_str(), O_RDONLY);
@@ -168,40 +161,27 @@ bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
 }
 
 bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
-  struct passwd pwd;
-  struct passwd *pwd_result;
-  char buf[kPWBufSize];
-  int ret = getpwuid_r(user, &pwd, buf, sizeof(buf), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr)
+  std::string username = ci::GetUsernameByUid(user);
+  if (username.empty())
     return {};
 
   bf::path apps_rw;
-  apps_rw = bf::path(apps_prefix.c_str()) / pwd.pw_name / "apps_rw";
-
+  apps_rw = bf::path(apps_prefix.c_str()) / username / "apps_rw";
   return apps_rw;
 }
 
 bool CreateUserDirectories(uid_t user, const std::string& pkgid,
     const std::string& apps_prefix, const bool set_permissions) {
-  struct passwd pwd;
-  struct passwd *pwd_result;
-  char buf_pw[kPWBufSize];
-  int ret = getpwuid_r(user, &pwd, buf_pw, sizeof(buf_pw), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr) {
-    LOG(WARNING) << "Failed to get user for home directory: " << user;
+  boost::optional<gid_t> gid = ci::GetGidByUid(user);
+  if (!gid)
     return false;
-  }
 
-  struct group gr;
-  struct group *gr_result;
-  char buf_gr[kGRBufSize];
-  ret = getgrgid_r(pwd.pw_gid, &gr, buf_gr, sizeof(buf_gr), &gr_result);
-  if (ret != 0
-      || strcmp(gr.gr_name, tzplatform_getenv(TZ_SYS_USER_GROUP)) != 0)
+  std::string group_name = ci::GetGroupNameByGid(*gid);
+  if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP))
     return false;
 
-  LOG(DEBUG) << "Creating directories for uid: " << pwd.pw_uid << ", gid: "
-             << pwd.pw_gid;
+  LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
+             << *gid;
 
   bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
   if (apps_rw.empty()) {
@@ -210,7 +190,7 @@ bool CreateUserDirectories(uid_t user, const std::string& pkgid,
   }
 
   if (!CreateDirectories(apps_rw, pkgid,
-      pwd.pw_uid, pwd.pw_gid, set_permissions)) {
+     user, *gid, set_permissions)) {
     return false;
   }
   return true;
@@ -227,32 +207,6 @@ bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
   return true;
 }
 
-user_list GetUserList() {
-  GumUserService* service =
-      gum_user_service_create_sync((getuid() == 0) ? TRUE : FALSE);
-  gchar** user_type_strv = gum_user_type_to_strv(
-      GUM_USERTYPE_ADMIN | GUM_USERTYPE_GUEST | GUM_USERTYPE_NORMAL |
-      GUM_USERTYPE_SECURITY);
-  GumUserList* gum_user_list =
-      gum_user_service_get_user_list_sync(service, user_type_strv);
-  user_list list;
-  for (GumUser* guser : GListRange<GumUser*>(gum_user_list)) {
-    uid_t uid;
-    g_object_get(G_OBJECT(guser), "uid", &uid, nullptr);
-    gid_t gid;
-    g_object_get(G_OBJECT(guser), "gid", &gid, nullptr);
-    gchar* homedir = nullptr;
-    g_object_get(G_OBJECT(guser), "homedir", &homedir, nullptr);
-    if (homedir == nullptr) {
-      LOG(WARNING) << "No homedir for uid: " << uid;
-      continue;
-    }
-    list.emplace_back(uid, gid, bf::path(homedir));
-  }
-  g_strfreev(user_type_strv);
-  gum_user_service_list_free(gum_user_list);
-  return list;
-}
 
 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
   std::vector<char*> rofiles;
@@ -395,7 +349,7 @@ bool PerformExternalDirectoryDeletionForUser(uid_t user,
 }
 
 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
                                                  pkgid))
@@ -419,7 +373,7 @@ int PrivilegeCallback(const pkgmgrinfo_pkginfo_h handle, void* user_data) {
 }
 
 bool PerformExternalDirectoryCreationForAllPkgs() {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l  : list) {
     uid_t uid = std::get<0>(l);
     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
@@ -448,7 +402,7 @@ bool PerformExternalDirectoryCreationForAllPkgs() {
 }
 
 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Deleting directories for user: " << uid;
@@ -519,7 +473,7 @@ bool DeleteSkelDirectories(const std::string& pkgid) {
 
 
 bool DeleteUserDirectories(const std::string& pkgid) {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     if (ci::QueryIsPackageInstalled(pkgid, std::get<0>(l))) {
       LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
@@ -537,7 +491,7 @@ bool DeleteUserDirectories(const std::string& pkgid) {
 }
 
 bool DeleteUserExternalDirectories(const std::string& pkgid) {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     if (ci::QueryIsPackageInstalled(pkgid, std::get<0>(l))) {
       LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
@@ -556,7 +510,7 @@ bool DeleteUserExternalDirectories(const std::string& pkgid) {
 
 
 bool CopyUserDirectories(const std::string& pkgid) {
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Copying directories for uid: " << uid;
@@ -593,7 +547,7 @@ bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
   }
 
   bool result = true;
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
@@ -638,7 +592,7 @@ bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
   }
 
   bool result = true;
-  user_list list = GetUserList();
+  UserList list = ci::GetUserList();
   for (auto l : list) {
     uid_t uid = std::get<0>(l);
     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
index da356af..a90f7f6 100644 (file)
@@ -83,7 +83,8 @@ Step::Status StepAcquireExternalStorage::process() {
 
   if (storage == Storage::EXTERNAL && !context_->external_storage) {
     if (!installed_) {
-      LOG(WARNING) << "Cannot initialize external storage for installed package";
+      LOG(WARNING) << "Cannot initialize external storage "
+                   << "for installed package";
       storage = Storage::INTERNAL;
     } else {
       LOG(ERROR) << "Cannot initialize external storage for updated package";
index 2c4c04e..5cfa7fd 100644 (file)
@@ -7,8 +7,6 @@
 
 #include <unistd.h>
 #include <sys/types.h>
-#include <grp.h>
-#include <pwd.h>
 #include <fcntl.h>
 #include <pkgmgr-info.h>
 #include <cassert>
 #include "common/shared_dirs.h"
 #include "common/utils/file_util.h"
 #include "common/utils/glist_range.h"
+#include "common/utils/user_util.h"
 
 namespace bf = boost::filesystem;
 namespace bs = boost::system;
+namespace ci = common_installer;
 
 namespace {
 
-const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
-const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
-
 bool SetOwner(const bf::path& subpath, uid_t uid, gid_t gid) {
   int fd = open(subpath.c_str(), O_RDONLY);
   if (fd < 0) {
@@ -92,40 +89,25 @@ Step::Status StepChangeOwner::precheck() {
 }
 
 Step::Status StepChangeOwner::process() {
-  struct passwd pwd;
-  struct passwd* pwd_result;
-  char buf_pw[kPWBufSize];
-
-  int ret = getpwuid_r(context_->uid.get(), &pwd, buf_pw,
-      sizeof(buf_pw), &pwd_result);
-  if (ret != 0 || pwd_result == nullptr) {
-    LOG(WARNING) << "Failed to get user for home directory: " <<
-        context_->uid.get();
-    return Status::ERROR;
-  }
-
-  struct group gr;
-  struct group* gr_result;
-  char buf_gr[kGRBufSize];
-  ret = getgrgid_r(pwd.pw_gid, &gr, buf_gr, sizeof(buf_gr), &gr_result);
-  if (ret != 0)
+  uid_t uid = context_->uid.get();
+  boost::optional<gid_t> gid = ci::GetGidByUid(uid);
+  if (!gid)
     return Status::ERROR;
 
   // Change owner of files at root path
   bf::path start_path = context_->pkg_path.get();
-  if (!SetOwner(start_path, pwd.pw_uid, pwd.pw_gid))
+  if (!SetOwner(start_path, uid, *gid))
     return Status::ERROR;
   for (bf::recursive_directory_iterator iter(start_path);
       iter != bf::recursive_directory_iterator(); ++iter) {
         if (bf::is_symlink(symlink_status(iter->path())))
           continue;
-        if (!SetOwner(iter->path(), pwd.pw_uid, pwd.pw_gid))
+        if (!SetOwner(iter->path(), uid, *gid))
           return Status::ERROR;
   }
 
   // For icon files
-  const char *iconpath = getIconPath(context_->uid.get(),
-      context_->is_preload_request.get());
+  const char *iconpath = getIconPath(uid, context_->is_preload_request.get());
   if (iconpath) {
     for (application_x* app :
         GListRange<application_x*>(
@@ -140,7 +122,7 @@ Step::Status StepChangeOwner::process() {
           context_->pkgid.get(), icon_path.filename(),
           context_->root_application_path.get());
       if (!found_icon_path.empty()) {
-        if (!SetOwner(found_icon_path, pwd.pw_uid, pwd.pw_gid))
+        if (!SetOwner(found_icon_path, uid, *gid))
           return Status::ERROR;
       }
     }
@@ -148,7 +130,7 @@ Step::Status StepChangeOwner::process() {
 
   // Manifest files for global apps
   if (!context_->xml_path.get().empty()) {
-    if (!SetOwner(context_->xml_path.get(), pwd.pw_uid, pwd.pw_gid))
+    if (!SetOwner(context_->xml_path.get(), uid, *gid))
       return Status::ERROR;
   }
 
index 6e0f864..672c5c1 100644 (file)
@@ -47,7 +47,8 @@ Step::Status StepOptionalAcquireExternalStorage::process() {
             context_->uid.get());
 
   if (storage == Storage::EXTERNAL && !context_->external_storage)
-      LOG(WARNING) << "Cannot initialize external storage for uninstalled package";
+      LOG(WARNING) << "Cannot initialize external storage "
+                   << "for uninstalled package";
 
   return Status::OK;
 }
diff --git a/src/common/utils/user_util.cc b/src/common/utils/user_util.cc
new file mode 100644 (file)
index 0000000..b30b782
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/utils/user_util.h"
+
+#include <manifest_parser/utils/logging.h>
+
+#include <boost/filesystem/path.hpp>
+
+#include <grp.h>
+#include <gum/gum-user.h>
+#include <gum/gum-user-service.h>
+#include <gum/common/gum-user-types.h>
+
+#include <vector>
+
+#include "common/utils/glist_range.h"
+
+namespace bf = boost::filesystem;
+
+namespace {
+
+const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
+const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
+
+}
+
+namespace common_installer {
+
+UserList GetUserList() {
+  GumUserService* service =
+      gum_user_service_create_sync((getuid() == 0) ? TRUE : FALSE);
+  gchar** user_type_strv = gum_user_type_to_strv(
+      GUM_USERTYPE_ADMIN | GUM_USERTYPE_GUEST | GUM_USERTYPE_NORMAL |
+      GUM_USERTYPE_SECURITY);
+  GumUserList* gum_user_list =
+      gum_user_service_get_user_list_sync(service, user_type_strv);
+  UserList list;
+  for (GumUser* guser : GListRange<GumUser*>(gum_user_list)) {
+    uid_t uid;
+    g_object_get(G_OBJECT(guser), "uid", &uid, nullptr);
+    gid_t gid;
+    g_object_get(G_OBJECT(guser), "gid", &gid, nullptr);
+    gchar* homedir = nullptr;
+    g_object_get(G_OBJECT(guser), "homedir", &homedir, nullptr);
+    if (homedir == nullptr) {
+      LOG(WARNING) << "No homedir for uid: " << uid;
+      continue;
+    }
+    list.emplace_back(uid, gid, bf::path(homedir));
+  }
+  g_strfreev(user_type_strv);
+  gum_user_service_list_free(gum_user_list);
+  return list;
+}
+
+boost::optional<gid_t> GetGidByGroupName(const char* groupname) {
+  boost::optional<gid_t> result;
+  char buf[kGRBufSize];
+  struct group entry;
+  struct group *ge;
+  int ret = getgrnam_r(groupname, &entry, buf, sizeof(buf), &ge);
+  if (ret || ge == nullptr) {
+    return result;
+  }
+  result = entry.gr_gid;
+  return result;
+}
+
+std::string GetUsernameByUid(uid_t user) {
+  struct passwd pwd;
+  struct passwd *pwd_result;
+  char buf[kPWBufSize];
+  int ret = getpwuid_r(user, &pwd, buf, sizeof(buf), &pwd_result);
+  if (ret != 0 || pwd_result == nullptr)
+    return {};
+  return pwd.pw_name;
+}
+
+boost::optional<gid_t> GetGidByUid(uid_t uid) {
+  boost::optional<gid_t> result;
+  struct passwd pwd;
+  struct passwd *pwd_result;
+  char buf[kPWBufSize];
+  int ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &pwd_result);
+  if (ret != 0 || pwd_result == nullptr)
+    return result;
+  result = pwd.pw_uid;
+  return result;
+}
+
+std::string GetGroupNameByGid(gid_t gid) {
+  char buf[kGRBufSize];
+  struct group entry;
+  struct group *ge;
+  int ret = getgrgid_r(gid, &entry, buf, sizeof(buf), &ge);
+  if (ret || ge == nullptr) {
+    return {};
+  }
+  return entry.gr_name;
+}
+
+}  // namespace common_installer
diff --git a/src/common/utils/user_util.h b/src/common/utils/user_util.h
new file mode 100644 (file)
index 0000000..2cf4368
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_USER_UTIL_H_
+#define COMMON_UTILS_USER_UTIL_H_
+
+#include <boost/filesystem/path.hpp>
+#include <boost/optional.hpp>
+
+#include <sys/types.h>
+
+#include <vector>
+#include <string>
+#include <tuple>
+
+namespace bf = boost::filesystem;
+
+namespace common_installer {
+
+typedef std::vector<std::tuple<uid_t, gid_t, bf::path>> UserList;
+
+UserList GetUserList();
+boost::optional<gid_t> GetGidByUid(uid_t uid);
+std::string GetGroupNameByGid(gid_t gid);
+std::string GetUsernameByUid(uid_t user);
+boost::optional<gid_t> GetGidByGroupName(const char* groupname);
+
+
+}  // namespace common_installer
+
+#endif  // COMMON_UTILS_USER_UTIL_H_