SET(TARGET_LIBNAME_TPK "tpk-installer")
SET(TARGET_WGT_BACKEND "wgt-backend")
SET(TARGET_TPK_BACKEND "tpk-backend")
-SET(TARGET_PKGDIR_TOOL "pkgdir-tool")
+SET(TARGET_PKGDIR_MAKER "pkgdir_maker.py")
ADD_DEFINITIONS("-Wall")
ADD_DEFINITIONS("-Wextra")
PKG_CHECK_MODULES(PRIVILEGE_CHECKER_DEPS REQUIRED capi-security-privilege-manager)
PKG_CHECK_MODULES(ENCRYPTION_DEPS REQUIRED libwebappenc)
PKG_CHECK_MODULES(APPMANAGER_DEPS REQUIRED capi-appfw-app-manager)
-PKG_CHECK_MODULES(LIBGUM_DEPS REQUIRED libgum)
-FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem regex program_options)
+FIND_PACKAGE(Boost REQUIRED COMPONENTS system filesystem regex)
FIND_PACKAGE(GTest REQUIRED)
ADD_SUBDIRECTORY(src)
<manifest>
- <request>
- <domain name="_" />
- </request>
- <assign>
- <filesystem path="/usr/bin/pkgdir-tool" exec_label="User" />
- </assign>
+ <request>
+ <domain name="_"/>
+ </request>
</manifest>
BuildRequires: pkgconfig(pkgmgr-info)
BuildRequires: pkgconfig(pkgmgr-installer)
BuildRequires: pkgconfig(security-manager)
-BuildRequires: pkgconfig(libgum)
BuildRequires: pkgconfig(libiri)
BuildRequires: pkgconfig(libxml-2.0)
BuildRequires: pkgconfig(zlib)
ln -s %{_bindir}/tpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/tpk
%post
+chown root:users %{_bindir}/pkgdir_maker
+chmod 4750 %{_bindir}/pkgdir_maker
+chmod 0700 %{_bindir}/pkgdir_maker_impl.sh
-%postun
-/sbin/ldconfig
+%postun -p /sbin/ldconfig
%files
%defattr(-,root,root)
%manifest app-installers.manifest
%{_libdir}/libcommon-installer.so*
-%attr(6750,root,users) %{_bindir}/pkgdir-tool
+%{_bindir}/pkgdir_maker_impl.sh
+%{_bindir}/pkgdir_maker
%license LICENSE
%files -n wgt-backend
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(wgt)
ADD_SUBDIRECTORY(tpk)
-ADD_SUBDIRECTORY(pkgdir_tool)
+ADD_SUBDIRECTORY(pkgdir_maker)
ADD_SUBDIRECTORY(unit_tests)
return PMINFO_R_OK;
}
-int PkgmgrForeachPrivilegeCallback(const char* privilege_name,
- void* user_data) {
- auto* data = static_cast<std::vector<std::string>*>(user_data);
- data->emplace_back(privilege_name);
- return PMINFO_R_OK;
-}
-
} // anonymous namespace
namespace common_installer {
return ret;
}
-bool QueryPrivilegesForPkgId(const std::string& pkg_id,
- std::vector<std::string>* result, uid_t uid) {
- pkgmgrinfo_pkginfo_h package_info;
- if (pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), uid, &package_info)
- != PMINFO_R_OK) {
- return false;
- }
-
- bool ret = pkgmgrinfo_pkginfo_foreach_privilege(package_info,
- &PkgmgrForeachPrivilegeCallback, result) == PMINFO_R_OK;
- pkgmgrinfo_pkginfo_destroy_pkginfo(package_info);
- return ret;
-}
-
bool IsPackageInstalled(const std::string& pkg_id, RequestMode request_mode) {
pkgmgrinfo_pkginfo_h handle;
int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), getuid(),
std::vector<std::string>* result, uid_t uid);
/**
- * \brief Adapter interface for external PkgMgr module used for getting
- * list of privileges for given package
- *
- * \param pkg_id id of package
- * \param result result - privileges
- * \param uid user id
- *
- * \return true if success
- */
-bool QueryPrivilegesForPkgId(const std::string& pkg_id,
- std::vector<std::string>* result, uid_t uid);
-
-/**
* \brief Adapter interface for external PkgMgr module used for checking
* if given package is installed/registered
*
};
bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
- const boost::filesystem::path& path,
- const std::vector<std::string>& privileges,
+ const boost::filesystem::path& path, manifest_x* manifest,
app_inst_req* req) {
if (app_id.empty() || pkg_id.empty()) {
LOG(ERROR) << "Appid or pkgid is empty. Both values must be set";
}
}
- for (auto& priv : privileges) {
- security_manager_app_inst_req_add_privilege(req, priv.c_str());
+ if (manifest) {
+ for (const char* priv : GListRange<char*>(manifest->privileges)) {
+ security_manager_app_inst_req_add_privilege(req, priv);
+ }
}
+
return true;
}
-} // namespace
-
-namespace common_installer {
-
bool RegisterSecurityContext(const std::string& app_id,
const std::string& pkg_id, const boost::filesystem::path& path,
- const std::vector<std::string>& privileges) {
+ manifest_x* manifest) {
app_inst_req* req;
int error = security_manager_app_inst_req_new(&req);
return false;
}
- if (!PrepareRequest(app_id, pkg_id, path, privileges, req)) {
+ if (!PrepareRequest(app_id, pkg_id, path, manifest, req)) {
LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
security_manager_app_inst_req_free(req);
return false;
return true;
}
+
bool UnregisterSecurityContext(const std::string& app_id,
const std::string& pkg_id) {
app_inst_req* req;
return false;
}
- if (!PrepareRequest(app_id, pkg_id, bf::path(), {}, req)) {
+ if (!PrepareRequest(app_id, pkg_id, bf::path(), nullptr, req)) {
LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
security_manager_app_inst_req_free(req);
return false;
return true;
}
-bool RegisterSecurityContextForManifest(
+} // namespace
+
+namespace common_installer {
+
+bool RegisterSecurityContextForApps(
const std::string& pkg_id, const boost::filesystem::path& path,
manifest_x* manifest) {
- std::vector<std::string> priv_vec;
- for (const char* priv : GListRange<char*>(manifest->privileges)) {
- priv_vec.emplace_back(priv);
- }
for (application_x* app : GListRange<application_x*>(manifest->application)) {
if (!app->appid) {
return false;
}
if (!RegisterSecurityContext(app->appid, pkg_id,
- path, priv_vec)) {
+ path, manifest)) {
return false;
}
}
return true;
}
-bool UnregisterSecurityContextForManifest(
+bool UnregisterSecurityContextForApps(
const std::string& pkg_id, manifest_x* manifest) {
for (application_x* app : GListRange<application_x*>(manifest->application)) {
if (!app->appid) {
#include <sys/types.h>
#include <string>
-#include <vector>
#include "common/installer_context.h"
* Adapter interface for external Security module used for registering
* application to security context
*
- * \param app_id id of given application
- * \param pkg_id id of given package
- * \param path path of installed package
- * \param privileges pointer to manifest structure
- *
- * \return true if success
- */
-bool RegisterSecurityContext(const std::string& app_id,
- const std::string& pkg_id, const boost::filesystem::path& path,
- const std::vector<std::string>& privileges);
-
-/**
- * Adapter interface for external Security module.
- *
- * Adapter interface for external Security module used for unregistering
- * application from security context
- *
- * \param app_id id of given application
- * \param pkg_id id of given package
- *
- * \return true if success
- */
-bool UnregisterSecurityContext(const std::string& app_id,
- const std::string& pkg_id);
-
-/**
- * Adapter interface for external Security module.
- *
- * Adapter interface for external Security module used for registering
- * package to security context
- *
- * \param pkg_id pkgid of given package
+ * \param pkg_id pkdid of given package
* \param path path of installed package
* \param manifest pointer to manifest structure
*
* \return true if success
*/
-bool RegisterSecurityContextForManifest(const std::string& pkg_id,
+bool RegisterSecurityContextForApps(const std::string& pkg_id,
const boost::filesystem::path& path, manifest_x* manifest);
/**
* Adapter interface for external Security module.
*
* Adapter interface for external Security module used for unregistering
- * package from security context
+ * application from security context
*
- * \param pkg_id pkgid of given package
+ * \param pkg_id pkdid of given package
* \param manifest pointer to manifest structure
*
* \return true if success
*/
-bool UnregisterSecurityContextForManifest(const std::string& pkg_id,
+bool UnregisterSecurityContextForApps(const std::string& pkg_id,
manifest_x* manifest);
} // namespace common_installer
namespace {
-const char kCache[] = "cache";
const char kDataLocation[] = "data";
const char kSharedLocation[] = "shared";
return Status::ERROR;
}
- if (!CacheDir())
- return Status::ERROR;
-
return Status::OK;
}
return ret;
}
-bool StepCopyStorageDirectories::CacheDir() {
- bs::error_code error_code;
- bf::path cache_path = context_->pkg_path.get() / kCache;
- bf::create_directory(cache_path, error_code);
- if (error_code) {
- LOG(ERROR) << "Failed to create cache directory for package";
- return false;
- }
- return true;
-}
-
} // namespace filesystem
} // namespace common_installer
bool MoveAppStorage(const boost::filesystem::path& in_src,
const boost::filesystem::path& in_dst,
const char *key);
- bool CacheDir();
+
boost::filesystem::path backup_path_;
+
SCOPE_LOG_TAG(CopyStorageDirectories)
};
namespace {
-const char kCache[] = "cache";
const char kData[] = "data";
const char kShared[] = "shared";
const char kSharedData[] = "data";
return Status::ERROR;
if (!PrivateDir())
return Status::ERROR;
- if (!CacheDir())
- return Status::ERROR;
return Status::OK;
}
bool StepCreateStorageDirectories::PrivateDir() {
bs::error_code error_code;
bf::path data_path = context_->pkg_path.get() / kData;
-
- // compatibility for old tpk packages
- if (bf::exists(data_path)) {
- LOG(DEBUG) << "Data directory already exists";
- return true;
- }
-
bf::create_directory(data_path, error_code);
if (error_code) {
LOG(ERROR) << "Failed to create private directory for package";
return true;
}
-bool StepCreateStorageDirectories::CacheDir() {
- bs::error_code error_code;
- bf::path cache_path = context_->pkg_path.get() / kCache;
- bf::create_directory(cache_path, error_code);
- if (error_code) {
- LOG(ERROR) << "Failed to create cache directory for package";
- return false;
- }
- return true;
-}
-
} // namespace filesystem
} // namespace common_installer
bool ShareDir();
bool SubShareDir();
bool PrivateDir();
- bool CacheDir();
SCOPE_LOG_TAG(CreateStorageDirectories)
};
Step::Status StepRecoverSecurity::RecoveryNew() {
if (!Check())
return Status::OK;
- UnregisterSecurityContextForManifest(
+ UnregisterSecurityContextForApps(
context_->pkgid.get(), context_->manifest_data.get());
return Status::OK;
}
LOG(ERROR) << "Invalid parameters";
return Status::ERROR;
}
- if (!RegisterSecurityContextForManifest(
+ if (!RegisterSecurityContextForApps(
context_->pkgid.get(), context_->pkg_path.get(),
context_->manifest_data.get())) {
LOG(ERROR) << "Unsuccessful update";
}
Step::Status StepRegisterSecurity::process() {
- if (!RegisterSecurityContextForManifest(
+ if (!RegisterSecurityContextForApps(
context_->pkgid.get(), context_->pkg_path.get(),
context_->manifest_data.get())) {
return Status::ERROR;
}
Step::Status StepRevokeSecurity::clean() {
- if (!UnregisterSecurityContextForManifest(
+ if (!UnregisterSecurityContextForApps(
context_->pkgid.get(), context_->manifest_data.get())) {
LOG(ERROR) << "Failure on unregistering security context for app "
<< context_->pkgid.get();
}
Step::Status StepRollbackDeinstallationSecurity::undo() {
- if (!RegisterSecurityContextForManifest(
+ if (!RegisterSecurityContextForApps(
context_->pkgid.get(), context_->pkg_path.get(),
context_->manifest_data.get())) {
LOG(ERROR) << "Failure on re-installing security context for app "
}
Step::Status StepRollbackInstallationSecurity::undo() {
- if (!UnregisterSecurityContextForManifest(
+ if (!UnregisterSecurityContextForApps(
context_->pkgid.get(), context_->manifest_data.get())) {
return Status::ERROR;
}
namespace security {
Step::Status StepUpdateSecurity::process() {
- if (!RegisterSecurityContextForManifest(
+ if (!RegisterSecurityContextForApps(
context_->pkgid.get(), context_->pkg_path.get(),
context_->manifest_data.get())) {
return Status::ERROR;
}
Step::Status StepUpdateSecurity::undo() {
- if (!RegisterSecurityContextForManifest(
+ if (!RegisterSecurityContextForApps(
context_->pkgid.get(), context_->pkg_path.get(),
context_->old_manifest_data.get())) {
return Status::ERROR;
--- /dev/null
+add_executable(pkgdir_maker "pkgdir_maker.cc")
+
+INSTALL(FILES
+ ${CMAKE_CURRENT_SOURCE_DIR}/pkgdir_maker_impl.sh
+ ${CMAKE_CURRENT_BINARY_DIR}/pkgdir_maker
+ DESTINATION ${BINDIR})
+
--- /dev/null
+/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+
+/* pkgdir_maker.cc
+ * A tool creating/deleting data directories of global app packages.
+ *
+ * Global apps are installed in /usr/apps/, but this path is not allowed for
+ * users to write their data. To store app data of global apps, the data and
+ * cache directories have to be created.
+ *
+ * This tool does two things:
+ * 1. creates the global app package's data and cache directories
+ * ({pkgid}/data, {pkgid}/cache) into all user's apps_rw/ directories.
+ * Proper owner, group, permission and SMACK labels are set for those dirs.
+ * 2. For new users in the future, the same directories are create into the
+ * user home template, /etc/skel/.
+ *
+ * NOTE: For prototyping, actual implementation is made as a bash script
+ * (pkgdir_maker_impl.sh), but later it is to be replaced with native code.
+ */
+
+#include <errno.h>
+#include <libgen.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define BUFSIZE 1024
+
+int main(int argc, char** argv) {
+ char cmd[BUFSIZE] = {0, };
+ char tmp[BUFSIZE] = {0, };
+ int i;
+
+ snprintf(cmd, BUFSIZE, "pkgdir_maker_impl.sh");
+
+ for (i=1; i < argc; i++) {
+ snprintf(tmp, BUFSIZE, "%s %s", cmd, argv[i]);
+ snprintf(cmd, BUFSIZE, "%s", tmp);
+ }
+
+ // set uid to root
+ // NOTE: Even the setuid permission is set to the executable,
+ // this routine is needed.
+ setuid(0);
+ seteuid(0);
+
+ return system(cmd);
+}
--- /dev/null
+#!/bin/bash
+# Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file
+VERSION="0.1.0"
+
+### CONFIG
+CONFIG_HomeDir="/home"
+CONFIG_UserAppDir="${CONFIG_HomeDir}/_USERID_/apps_rw"
+CONFIG_UserGroup="users"
+CONFIG_SkelAppDir="/etc/skel/apps_rw"
+CONFIG_SkelOwner="root"
+CONFIG_SkelGroup="root"
+
+
+### Directories to be created
+DIRS=( DIR_root DIR_data DIR_cache )
+# path type owner group permission SMACK_label SMACK_transmute SMACK_exec
+DIR_root=( "_PKGID_" "d" "_USERNAME_" "_USERGROUP_" 750 "User::Home" 1 0 )
+DIR_data=( "_PKGID_/data" "d" "_USERNAME_" "_USERGROUP_" 750 "User::Pkg::_PKGID_" 1 0 )
+DIR_cache=( "_PKGID_/cache" "d" "_USERNAME_" "_USERGROUP_" 750 "User::Pkg::_PKGID_" 1 0 )
+
+
+### Utils
+## Print log
+function LOG
+{
+ LABEL=$1
+ MSG="[${LABEL}] $2"
+ # Skip printing debug log without OPTION_verbose
+ if [[ ${LABEL} == "DEBUG" && ! -n ${OPTION_verbose} ]]; then
+ return 0
+ fi
+ # Print log
+ echo -e "${MSG}"
+ # Exit if error log is given
+ if [[ "${LABEL}" == "ERROR" ]]; then
+ exit 1
+ fi
+ return 0
+}
+
+## Get valid user list
+# Returns: return_getUserList (the user list array)
+function getUserList
+{
+ return_getUserList=( ) # return variable(array)
+ local homeDirList=`ls ${CONFIG_HomeDir}`
+ for userName in ${homeDirList}; do
+ # if $HOME/apps_rw exists, it is assumed that the user exists.
+ local appDir=${CONFIG_UserAppDir/_USERID_/$userName}
+ if [[ -d "$appDir" ]]; then
+ LOG DEBUG "Check if $appDir/ exists... Found. user $userName is added."
+ # Append new item into array
+ return_getUserList[${#return_getUserList[*]}]="$userName"
+ else
+ LOG DEBUG "Check if $appDir/ exists... Not found."
+ fi
+ done
+}
+
+
+## Get real dirinfo
+# Returns: return_getDirInfo (Directory info array)
+function getDirInfo
+{
+ local dirname=$1
+ local pkgid=$2
+ local username=$3
+ local usergroup=$4
+ return_getDirInfo=( )
+
+ # NOTE: indirect reference + array copy
+ eval dirinfo_template=\( \${${dirname}[@]} \)
+
+ for value in "${dirinfo_template[@]}"; do
+ value=${value//_PKGID_/$pkgid}
+ value=${value//_USERNAME_/$username}
+ value=${value//_USERGROUP_/$usergroup}
+ return_getDirInfo[${#return_getDirInfo[*]}]=$value
+ done
+
+ return 0
+}
+
+
+## Create directory
+function createDir
+{
+ local path=$1
+ local pathtype=$2
+ local owner=$3
+ local group=$4
+ local permission=$5
+
+ mkdir -p $path || LOG ERROR "Directory creation failure: $path"
+ chown $owner:$group $path || LOG ERROR "chown failure: $path to $owner:$group"
+ chmod $permission $path || LOG ERROR "chmod failure: $path to $permission"
+
+ LOG DEBUG "Created directory: $path ($owner:$group, $permission)"
+
+ return 0
+}
+
+
+## Set SMACK
+function setSmackToPath
+{
+ local path=$1
+ local smack_label=$2
+ local smack_transmute=$3
+ local smack_exec=$4
+
+ chsmack -a $smack_label $path || LOG ERROR "SMACK labeling failure"
+ if [[ "${smack_transmute}" == "1" ]]; then
+ chsmack -t $path || LOG ERROR "SMACK transmute tagging failure"
+ fi
+ if [[ "${smack_exec}" == "1" ]]; then
+ chsmack -e $path || LOG ERROR "SMACK exec tagging failure"
+ fi
+ LOG DEBUG "Set SMACK to ${path}: label=${smack_label}, transmute=${smack_transmute}, exec=${smack_exec}"
+ return 0
+}
+
+
+## Create pkg dirs
+function createPkgDir
+{
+ local pkgid=$1
+ local username=$2
+ local usergroup=$3
+ local parentdir=$4
+
+ LOG INFO "Create package directory ${pkgid} into ${parentdir}"
+ for dirname in "${DIRS[@]}"; do
+ getDirInfo $dirname $pkgid $username $usergroup
+ local dirinfo=( "${return_getDirInfo[@]}" )
+
+ # Get each values
+ local path="${parentdir}/${dirinfo[0]}"
+ local pathtype=${dirinfo[1]}
+ local owner=${dirinfo[2]}
+ local group=${dirinfo[3]}
+ local permission=${dirinfo[4]}
+ local smack_label=${dirinfo[5]}
+ local smack_transmute=${dirinfo[6]}
+ local smack_exec=${dirinfo[7]}
+
+ createDir $path $pathtype $owner $group $permission
+ setSmackToPath $path $smack_label $smack_transmute $smack_exec
+
+ done
+}
+
+
+## Create pkg directories into given user's home directory
+function createPkgDirForUser
+{
+ local pkgid=$1
+ local username=$2
+ local group=$3
+
+ local parentdir=${CONFIG_UserAppDir/_USERID_/$username}
+
+ LOG DEBUG "createPkgDirForUser: pkgid=${pkgid}, parentdir=${parentdir}"
+ createPkgDir $pkgid $username $group $parentdir
+
+ return 0
+}
+
+
+## Create pkg directory into the skeleton
+function createPkgDirToSkeleton
+{
+ local pkgid=$1
+
+ local owner=${CONFIG_SkelOwner}
+ local group=${CONFIG_SkelGroup}
+ local parentdir=${CONFIG_SkelAppDir}
+
+ createPkgDir $pkgid $owner $group $parentdir
+
+ return 0
+}
+
+### create dirs
+function createDirs
+{
+ local pkgid=$1
+
+ # Get user list
+ getUserList
+ # NOTE: This return value is an array, so array copy is used.
+ local userList=( "${return_getUserList[@]}" )
+
+ echo "userList: ${userList[@]}"
+
+ for user in ${userList[@]}; do
+ createPkgDirForUser $pkgid $user $CONFIG_UserGroup
+ done
+
+ createPkgDirToSkeleton $pkgid
+
+ return 0
+}
+
+function deletePkgDirForUser
+{
+ local pkgid=$1
+ local username=$2
+
+ local parentdir=${CONFIG_UserAppDir/_USERID_/$username}
+ local appdir="${parentdir}/${pkgid}"
+
+ rm -rf $appdir || LOG ERROR "Removing directory failure: $appdir"
+ LOG INFO "${appdir} is removed"
+}
+
+function deletePkgDirFromSkeleton
+{
+ local pkgid=$1
+ local parentdir=${CONFIG_SkelAppDir}
+ local appdir="${parentdir}/${pkgid}"
+
+ rm -rf $appdir || LOG ERROR "Removing directory failure: $appdir"
+ LOG INFO "${appdir} is removed"
+}
+
+
+### delete dirs
+function deleteDirs
+{
+ local pkgid=$1
+
+ getUserList
+ local userList=( "${return_getUserList[@]}" )
+
+ for user in "${userList[@]}"; do
+ deletePkgDirForUser $pkgid $user
+ done
+ deletePkgDirFromSkeleton
+
+ return 0
+}
+
+
+### Option processing
+_valid_option_list=( "--create" "--delete" "--pkgid=" "--verbose" "--allglobalpkgs" "--help" )
+for option in $@
+do
+ found_option=0
+ for _valid_option in ${_valid_option_list[@]}
+ do
+ if [ "$_valid_option" == "${option:0:${#_valid_option}}" ]; then
+ if [ ${_valid_option:${#_valid_option}-1} == "=" ]; then
+ eval "export OPTION_${option#--}"
+ else
+ eval "export OPTION_${option#--}=1"
+ fi
+ found_option=1
+ break
+ fi
+ done
+ if [[ $found_option == 0 ]]; then
+ LOG ERROR "Invalid option: ${option}\nUsage: `basename $0` --help"
+ fi
+done
+if test -n "${OPTION_help}"; then
+ echo -e "`basename $0` ${VERSION}"
+ echo -e " Creates or deletes package data directories of given global apps"
+ echo -e " into all users' hone directories."
+ echo -e "Usage:"
+ echo -e " `basename $0` --create --pkgid=<pkgid> : Create package dirs"
+ echo -e " `basename $0` --delete --pkgid=<pkgid> : Delete package dirs"
+ echo -e " `basename $0` --create --allglobalpkgs : Create package dirs for all global packages"
+ exit 0
+fi
+if [[ -n "${OPTION_create}" && -n "${OPTION_delete}" ]]; then
+ LOG ERROR "--create and --delete cannot be used together"
+fi
+if [[ ! -n "${OPTION_pkgid}" && ! -n "${OPTION_allglobalpkgs}" ]]; then
+ LOG ERROR "pkgid is not given"
+fi
+
+
+### main
+if [[ -n "${OPTION_create}" ]]; then
+ if [[ -n "${OPTION_allglobalpkgs}" ]]; then
+ ls /usr/share/packages/*.xml | while read xmlfile;
+ do
+ pkgid=`cat $xmlfile | grep -aPzo '<manifest..*?>' | grep -Pzo 'package="..*?"' | sed -e 's/package="\(..*\)"/\1/'`
+ if [[ -n "${pkgid}" ]]; then
+ createDirs ${pkgid}
+ fi
+ done
+ else
+ createDirs ${OPTION_pkgid}
+ fi
+elif [[ -n "${OPTION_delete}" ]]; then
+ deleteDirs ${OPTION_pkgid}
+fi
+
+
+echo "Done."
+exit 0
+++ /dev/null
-# Target - sources
-SET(SRCS
- pkgdir_tool.cc
-)
-
-# Target - definition
-ADD_EXECUTABLE(${TARGET_PKGDIR_TOOL} "pkgdir_tool.cc")
-# Target - includes
-TARGET_INCLUDE_DIRECTORIES(${TARGET_PKGDIR_TOOL} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../")
-# Target - deps
-APPLY_PKG_CONFIG(${TARGET_PKGDIR_TOOL} PUBLIC
- LIBGUM_DEPS
- PKGMGR_INSTALLER_DEPS
-)
-# Target - in-package deps
-TARGET_LINK_LIBRARIES(${TARGET_PKGDIR_TOOL} PUBLIC ${TARGET_LIBNAME_COMMON})
-
-# Install
-INSTALL(TARGETS ${TARGET_PKGDIR_TOOL} DESTINATION ${BINDIR})
-
-
+++ /dev/null
-// Copyright (c) 2015 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 <boost/filesystem/operations.hpp>
-#include <boost/filesystem/path.hpp>
-#include <boost/program_options.hpp>
-#include <boost/system/error_code.hpp>
-
-#include <gum/common/gum-user-types.h>
-#include <gum/gum-user-service.h>
-#include <gum/gum-user.h>
-#include <pkgmgr-info.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <tzplatform_config.h>
-
-#include <cassert>
-#include <cstring>
-#include <exception>
-#include <regex>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "common/security_registration.h"
-#include "common/pkgmgr_registration.h"
-#include "common/utils/file_util.h"
-#include "common/utils/glist_range.h"
-#include "common/utils/logging.h"
-
-namespace bf = boost::filesystem;
-namespace bpo = boost::program_options;
-namespace bs = boost::system;
-namespace ci = common_installer;
-
-namespace {
-
-enum class Action {
- CREATE,
- COPY_OR_CREATE
-};
-
-const std::vector<std::pair<const char*, Action>> kEntries = {
- {"/", Action::CREATE},
- {"cache/", Action::CREATE},
- {"data/", Action::COPY_OR_CREATE} // compatibility -> copy data/ dir for tpk
-};
-
-const char kSkelAppDir[] = "/etc/skel/apps_rw";
-const char kAppsRwLocation[] = "apps_rw";
-const char kPackagePattern[] = R"(^[0-9a-zA-Z_-]+(\.?[0-9a-zA-Z_-]+)*$)";
-
-bool ValidateTizenPackageId(const std::string& id) {
- std::regex package_regex(kPackagePattern);
- return std::regex_match(id, package_regex);
-}
-
-int PkgmgrListCallback(const pkgmgrinfo_pkginfo_h handle, void *user_data) {
- std::vector<std::string>* pkgids =
- reinterpret_cast<std::vector<std::string>*>(user_data);
- char* pkgid = nullptr;
- if (pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid) != PMINFO_R_OK) {
- return -1;
- }
- pkgids->emplace_back(pkgid);
- return 0;
-}
-
-std::vector<std::string> GetAllGlobalApps() {
- std::vector<std::string> pkgids;
- if (pkgmgrinfo_pkginfo_get_usr_list(&PkgmgrListCallback,
- &pkgids, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) != PMINFO_R_OK) {
- LOG(ERROR) << "Failed to query global application list";
- return {};
- }
- return pkgids;
-}
-
-class ScopedUser {
- public:
- ScopedUser(uid_t uid) {
- uid_ = geteuid();
- assert(seteuid(uid) == 0);
- }
- ~ScopedUser() {
- assert(seteuid(uid_) == 0);
- }
- private:
- uid_t uid_;
-};
-
-bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
- uid_t uid, gid_t gid) {
- bf::path base_dir = app_dir / pkgid;
- if (bf::exists(base_dir)) {
- LOG(DEBUG) << "Directory for user already exist: " << base_dir;
- return true;
- }
-
- bs::error_code error;
- for (auto& pair : kEntries) {
- bf::path subpath = base_dir / pair.first;
- switch (pair.second) {
- case Action::COPY_OR_CREATE: {
- bf::path global_directory =
- bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid / pair.first;
- if (bf::exists(global_directory)) {
- if (!ci::CopyDir(global_directory, subpath)) {
- LOG(ERROR) << "Failed to copy directory: " << global_directory;
- return false;
- }
- break;
- }
- }
- case Action::CREATE: {
- bf::create_directories(subpath, error);
- if (error) {
- LOG(ERROR) << "Failed to create directory: " << subpath;
- return false;
- }
- break;
- }
- default:
- assert(false);
- }
-
- bf::permissions(subpath,
- bf::owner_read | bf::owner_write | bf::owner_exe |
- bf::group_read | bf::group_exe, error);
- if (error) {
- LOG(ERROR) << "Failed to set permissions for: " << subpath;
- return false;
- }
- int ret = chown(subpath.c_str(), uid, gid);
- if (ret != 0) {
- LOG(ERROR) << "Failed to change owner of: " << subpath;
- return false;
- }
-
- // for content
- for (bf::recursive_directory_iterator iter(subpath);
- iter != bf::recursive_directory_iterator(); ++iter) {
- bf::perms perms = bf::owner_read |
- bf::owner_write |
- bf::group_read;
- if (bf::is_directory(iter->path())) {
- perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
- }
- bf::permissions(iter->path(), perms, error);
- if (error) {
- LOG(ERROR) << "Failed to set permissions for: " << iter->path();
- return false;
- }
- int ret = chown(iter->path().c_str(), uid, gid);
- if (ret != 0) {
- LOG(ERROR) << "Failed to change owner of: " << iter->path();
- return false;
- }
- }
- }
-
- // set smack
- ScopedUser scoped_user(uid);
- if (!pkgid.empty()) {
- std::vector<std::string> privileges;
- std::vector<std::string> appids;
- if (!common_installer::QueryPrivilegesForPkgId(pkgid, &privileges,
- tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))) {
- LOG(ERROR) << "Failed to get privileges for package id";
- return false;
- }
- if (!common_installer::QueryAppidsForPkgId(pkgid, &appids,
- tzplatform_getuid(TZ_SYS_GLOBALAPP_USER))) {
- LOG(ERROR) << "Failed to get application ids for package id";
- return false;
- }
- for (auto& appid : appids) {
- if (!common_installer::RegisterSecurityContext(appid, pkgid, base_dir,
- privileges)) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool CreatePerUserDirectories(const std::string& pkgid) {
- GumUserService* service = gum_user_service_create_sync(TRUE);
- if (!service) {
- LOG(ERROR) << "gum_user_service_create_sync failed";
- return false;
- }
- GumUserList* users = gum_user_service_get_user_list_sync(service, nullptr);
-
- bool result = true;
- for (GumUser* user : GListRange<GumUser*>(users)) {
- GumUserType ut = GUM_USERTYPE_NONE;
- g_object_get(G_OBJECT(user), "usertype", &ut, NULL);
- if (ut != GUM_USERTYPE_ADMIN && ut != GUM_USERTYPE_GUEST &&
- ut != GUM_USERTYPE_NORMAL)
- continue;
-
- uid_t uid;
- g_object_get(G_OBJECT(user), "uid", &uid, NULL);
- gid_t gid;
- g_object_get(G_OBJECT(user), "gid", &gid, NULL);
-
- gchar* home_dir = nullptr;
- g_object_get(G_OBJECT(user), "homedir", &home_dir, nullptr);
- bf::path home_path(home_dir);
- g_free(home_dir);
- if (!bf::exists(home_path)) {
- LOG(WARNING) << home_path << " doesn't exist";
- continue;
- }
- LOG(DEBUG) << "Creating directories for uid: " << uid << ", gid: " << gid
- << ", home: " << home_path;
- if (!CreateDirectories(home_path / kAppsRwLocation, pkgid, uid, gid)) {
- result = false;
- break;
- }
- }
- gum_user_service_list_free(users);
- g_object_unref(service);
- return result;
-}
-
-bool CreateSkelDirectories(const std::string& pkgid) {
- bf::path path = bf::path(kSkelAppDir) / pkgid;
- LOG(DEBUG) << "Creating directories in: " << path;
- bs::error_code error;
- bf::create_directories(path, error);
- if (error) {
- LOG(ERROR) << "Failed to create directory: " << path;
- return false;
- }
- return true;
-}
-
-bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
- bf::path base_dir = app_dir / pkgid;
- bs::error_code error;
- bf::remove_all(base_dir, error);
- if (error) {
- LOG(ERROR) << "Failed to delete directory: " << base_dir;
- return false;
- }
- return true;
-}
-
-bool DeletePerUserDirectories(const std::string& pkgid) {
- GumUserService* service = gum_user_service_create_sync(TRUE);
- if (!service) {
- LOG(ERROR) << "gum_user_service_create_sync failed";
- return false;
- }
- GumUserList* users = gum_user_service_get_user_list_sync(service, nullptr);
-
- bool result = true;
- for (GumUser* user : GListRange<GumUser*>(users)) {
- GumUserType ut = GUM_USERTYPE_NONE;
- g_object_get(G_OBJECT(user), "usertype", &ut, NULL);
- if (ut != GUM_USERTYPE_ADMIN && ut != GUM_USERTYPE_GUEST &&
- ut != GUM_USERTYPE_NORMAL)
- continue;
-
- uid_t uid;
- g_object_get(G_OBJECT(user), "uid", &uid, NULL);
- gid_t gid;
- g_object_get(G_OBJECT(user), "gid", &gid, NULL);
-
- gchar* home_dir = nullptr;
- g_object_get(G_OBJECT(user), "homedir", &home_dir, nullptr);
- bf::path home_path(home_dir);
- g_free(home_dir);
- if (!bf::exists(home_path)) {
- LOG(WARNING) << home_path << " doesn't exist";
- continue;
- }
- LOG(DEBUG) << "Deleting directories for uid: " << uid << ", gid: " << gid;
- if (!DeleteDirectories(home_path / kAppsRwLocation, pkgid)) {
- result = false;
- break;
- }
- }
- gum_user_service_list_free(users);
- g_object_unref(service);
- return result;
-}
-
-bool DeleteSkelDirectories(const std::string& pkgid) {
- bf::path path = bf::path(kSkelAppDir) / pkgid;
- LOG(DEBUG) << "Deleting directories in: " << path;
- bs::error_code error;
- bf::remove_all(path, error);
- if (error) {
- LOG(ERROR) << "Failed to delete directory: " << path;
- return false;
- }
- return true;
-}
-
-bool PerformDirectoryCreation(const std::string& pkgid) {
- if (!CreatePerUserDirectories(pkgid))
- return false;
- if (!CreateSkelDirectories(pkgid))
- return false;
- return true;
-}
-
-bool PerformDirectoryDeletion(const std::string& pkgid) {
- if (!DeletePerUserDirectories(pkgid))
- return false;
- if (!DeleteSkelDirectories(pkgid))
- return false;
- return true;
-}
-
-void ExclusiveOptions(const bpo::variables_map& vm,
- const std::string& opt1, const std::string& opt2) {
- if ((vm.count(opt1) && vm.count(opt2)) ||
- (!vm.count(opt1) && !vm.count(opt2))) {
- throw std::logic_error(std::string("Exclusive options '") +
- opt1 + "' and '" + opt2 + "'.");
- }
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- bpo::options_description options("Allowed options");
- options.add_options()
- ("create", "create per user diretories for global package")
- ("delete", "delete per user diretories for global package")
- ("allglobalpkgs", "install directories for all global applications")
- ("pkgid", bpo::value<std::string>(), "package ID");
- bpo::variables_map opt_map;
- try {
- bpo::store(bpo::parse_command_line(argc, argv, options), opt_map);
- ExclusiveOptions(opt_map, "create", "delete");
- ExclusiveOptions(opt_map, "pkgid", "allglobalpkgs");
- bpo::notify(opt_map);
- } catch(const std::exception& error) {
- LOG(ERROR) << error.what();
- return -1;
- }
-
- bool create_mode = opt_map.count("create") != 0;
- bool delete_mode = opt_map.count("delete") != 0;
- bool allglobalpkgs = opt_map.count("allglobalpkgs") != 0;
- std::string pkgid;
- if (opt_map.count("pkgid")) {
- pkgid = opt_map["pkgid"].as<std::string>();
- if (!ValidateTizenPackageId(pkgid)) {
- LOG(ERROR) << "Pkgid is invalid";
- return -1;
- }
- }
- std::vector<std::string> pkgids;
- if (allglobalpkgs) {
- pkgids = GetAllGlobalApps();
- } else {
- pkgids.push_back(pkgid);
- }
-
- assert(setuid(0) == 0);
-
- if (create_mode) {
- for (auto& package_id : pkgids) {
- LOG(DEBUG) << "Running for package id: " << package_id;
- if (!PerformDirectoryCreation(package_id))
- return -1;
- }
- } else if (delete_mode) {
- for (auto& package_id : pkgids) {
- LOG(DEBUG) << "Running for package id: " << package_id;
- if (!PerformDirectoryDeletion(package_id))
- return -1;
- }
- }
- return 0;
-}
bf::path binary_path = package_path / "bin" / appid;
bf::path data_path = package_path / "data";
bf::path shared_path = package_path / "shared";
- bf::path cache_path = package_path / "cache";
ASSERT_TRUE(bf::exists(root_path));
ASSERT_TRUE(bf::exists(package_path));
ASSERT_TRUE(bf::exists(binary_path));
ASSERT_TRUE(bf::exists(data_path));
ASSERT_TRUE(bf::exists(shared_path));
- ASSERT_TRUE(bf::exists(cache_path));
bf::path manifest_path =
bf::path(getUserManifestPath(getuid())) / (pkgid + ".xml");
ASSERT_TRUE(bf::exists(config_path));
bf::path private_tmp_path = package_path / "tmp";
+ bf::path cache_path = package_path / "cache";
ASSERT_TRUE(bf::exists(private_tmp_path));
+ ASSERT_TRUE(bf::exists(cache_path));
}
// backups should not exist
const char kSharedTrustedLocation[] = "shared/trusted";
const char kResWgtSubPath[] = "res/wgt";
const char kTemporaryData[] = "tmp";
+const char kCacheDir[] = "cache";
+
} // namespace
namespace wgt {
Status status = CreatePrivateTmpDir();
if (status != Status::OK)
return status;
- if (!CacheDir())
- return Status::ERROR;
+ status = CreateCacheDir();
+ if (status != Status::OK)
+ return status;
int version = context_->manifest_data.get()->api_version[0] - '0';
if (version < 3) {
return Status::OK;
}
+common_installer::Step::Status
+StepWgtCopyStorageDirectories::CreateCacheDir() {
+ bs::error_code error_code;
+ bf::path cache_path = context_->pkg_path.get() / kCacheDir;
+ bf::create_directory(cache_path, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create cache directory for package";
+ return Status::ERROR;
+ }
+ return Status::OK;
+}
+
} // namespace filesystem
} // namespace wgt
void UndoSharedDirectory();
void UndoDataDirectory();
Status CreatePrivateTmpDir();
+ Status CreateCacheDir();
SCOPE_LOG_TAG(CopyWgtStorageDirectories)
};
const char kSharedLocation[] = "shared";
const char kResWgtSubPath[] = "res/wgt";
const char kTemporaryData[] = "tmp";
+const char kCacheDir[] = "cache";
} // namespace
if (!CreatePrivateTmpDir())
return Status::ERROR;
- if (!CacheDir())
+ if (!CreateCacheDir())
return Status::ERROR;
return Status::OK;
return true;
}
+bool StepWgtCreateStorageDirectories::CreateCacheDir() {
+ bs::error_code error_code;
+ bf::path cache_path = context_->pkg_path.get() / kCacheDir;
+ bf::create_directory(cache_path, error_code);
+ if (error_code) {
+ LOG(ERROR) << "Failed to create cache directory for package";
+ return false;
+ }
+ return true;
+}
+
} // namespace filesystem
} // namespace wgt
bool ShareDirFor3x();
bool CreatePrivateTmpDir();
+ bool CreateCacheDir();
SCOPE_LOG_TAG(CreateWgtStorageDirectories)
};