step/filesystem/step_copy.cc
step/filesystem/step_copy_storage_directories.cc
step/filesystem/step_copy_tep.cc
+ step/filesystem/step_create_globalapp_symlinks.cc
step/filesystem/step_create_icons.cc
step/filesystem/step_create_per_user_storage_directories.cc
step/filesystem/step_create_legacy_directories.cc
step/filesystem/step_recover_external_storage.cc
step/filesystem/step_recover_storage_directories.cc
step/filesystem/step_remove_files.cc
+ step/filesystem/step_remove_globalapp_symlinks.cc
step/filesystem/step_remove_icons.cc
step/filesystem/step_remove_per_user_storage_directories.cc
step/filesystem/step_remove_legacy_directories.cc
const char kDBusObjectPath[] = "/org/tizen/pkgdir_tool";
const char kDBusInterfaceName[] = "org.tizen.pkgdir_tool";
-bool RequestUserDirectoryOperation(const char* method,
- const std::string& pkgid) {
+bool DBusRequestForDirectoryOperation(const char* method,
+ GVariant* parameter) {
GError* err = nullptr;
GDBusConnection* con = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
if (!con || err) {
return false;
}
GVariant* r = g_dbus_proxy_call_sync(proxy, method,
- g_variant_new("(s)", pkgid.c_str()), G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
+ parameter, G_DBUS_CALL_FLAGS_NONE, -1, nullptr,
&err);
if (!r) {
std::string err_msg;
return result;
}
+bool RequestUserDirectoryOperation(const char* method,
+ const std::string& pkgid) {
+ GVariant* parameter = g_variant_new("(s)", pkgid.c_str());
+ return DBusRequestForDirectoryOperation(method, parameter);
+}
+
+bool RequestUserDirectoryOperationForUser(const char* method,
+ const std::string& pkgid, uid_t uid) {
+ GVariant* parameter = g_variant_new("(si)", pkgid.c_str(), uid);
+ return DBusRequestForDirectoryOperation(method, parameter);
+}
+
} // namespace
namespace common_installer {
return true;
}
+bool RequestCreateGlobalAppSymlinks(const std::string& pkgid) {
+ bool result =
+ RequestUserDirectoryOperation("CreateGlobalAppSymlinks", pkgid);
+ if (!result) {
+ LOG(INFO) << "Try to create symlinks for global app directly";
+ return CreateGlobalAppSymlinksForAllUsers(pkgid);
+ }
+ return result;
+}
+
+bool RequestCreateGlobalAppSymlinksForUser(const std::string& pkgid,
+ uid_t uid) {
+ bool result =
+ RequestUserDirectoryOperationForUser("CreateGlobalAppSymlinksForUser",
+ pkgid, uid);
+ if (!result) {
+ LOG(INFO) << "Try to create symlinks for global app directly";
+ return CreateGlobalAppSymlinksForUser(pkgid, uid);
+ }
+ return result;
+}
+
+bool RequestDeleteGlobalAppSymlinks(const std::string& pkgid) {
+ bool result =
+ RequestUserDirectoryOperation("DeleteGlobalAppSymlinks", pkgid);
+ if (!result) {
+ LOG(INFO) << "Try to delete symlinks for global app directly";
+ return DeleteGlobalAppSymlinksForAllUsers(pkgid);
+ }
+ return result;
+}
+
+bool RequestDeleteGlobalAppSymlinksForUser(const std::string& pkgid,
+ uid_t uid) {
+ bool result =
+ RequestUserDirectoryOperationForUser("DeleteGlobalAppSymlinksForUser",
+ pkgid, uid);
+ if (!result) {
+ LOG(INFO) << "Try to delete symlinks for global app directly";
+ return DeleteGlobalAppSymlinksForUser(pkgid, uid);
+ }
+ return result;
+}
+
} // namespace common_installer
*/
bool RequestDeleteLegacyDirectories(const std::string& pkgid);
+/**
+ * \brief Request to create symlinks of global app for all users
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestCreateGlobalAppSymlinks(const std::string& pkgid);
+
+/**
+ * \brief Request to create symlinks of global app for user
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestCreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Request to delete symlinks of global app for all users
+ *
+ * \param pkgid package id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestDeleteGlobalAppSymlinks(const std::string& pkgid);
+
+/**
+ * \brief Request to delete symlinks of global app for user
+ *
+ * \param pkgid package id
+ * \param uid user id
+ *
+ * \return bool true if succeed, false otherwise
+ */
+bool RequestDeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
} // namespace common_installer
#endif // COMMON_PKGDIR_TOOL_REQUEST_H_
for (auto& policy : kSecurityPolicies) {
bf::path subpath = path / policy.first;
if (bf::exists(subpath)) {
- if (bf::is_symlink(subpath)) {
+ if (bf::is_symlink(symlink_status(subpath))) {
LOG(DEBUG) << "Path " << subpath << " is a symlink."
<< "Path will not be registered";
continue;
for (auto& policy : kSecurityPolicies) {
bf::path subpath = path / policy.first;
if (bf::exists(subpath)) {
- if (bf::is_symlink(subpath)) {
+ if (bf::is_symlink(symlink_status(subpath))) {
LOG(DEBUG) << "Path " << subpath << " is a symlink."
<< "Path will not be registered";
continue;
{"data/"},
{"shared/"},
};
+const std::vector<const char*> kReadOnlyEntries = {
+ {"bin"},
+ {"lib"},
+ {"res"},
+ {"shared/res"},
+};
+const char kSharedResDir[] = "shared/res";
const char kSharedDataDir[] = "shared/data";
const char kSharedTrustedDir[] = "shared/trusted";
const char kSkelAppDir[] = "/etc/skel/apps_rw";
-const char kLegacyAppDir[] = "/opt/usr/apps";
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 SetOwnerAndPermissions(const bf::path& subpath, uid_t uid,
- gid_t gid, bf::perms perms) {
+bool SetFileOwner(const bf::path& subpath, uid_t uid, gid_t gid) {
bs::error_code error;
- bf::permissions(subpath, perms, error);
- if (error) {
- LOG(ERROR) << "Failed to set permissions for: " << subpath;
- return false;
- }
int fd = open(subpath.c_str(), O_RDONLY);
if (fd < 0) {
LOG(ERROR) << "Can't open directory : " << subpath;
return true;
}
-bool SetPackageDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
- gid_t gid) {
+bool SetOwnerAndPermissions(const bf::path& subpath, uid_t uid,
+ gid_t gid, bf::perms perms) {
bs::error_code error;
- bf::perms perms = bf::owner_read |
- bf::owner_write |
- bf::group_read;
- if (bf::is_directory(subpath))
- perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
+ bf::permissions(subpath, perms, error);
+ if (error) {
+ LOG(ERROR) << "Failed to set permissions for: " << subpath;
+ return false;
+ }
- return SetOwnerAndPermissions(subpath, uid, gid, perms);
+ if (!SetFileOwner(subpath, uid, gid)) {
+ return false;
+ }
+ return true;
}
-bool SetLegacyDirectoryOwnerAndPermissions(const bf::path& subpath) {
+bool SetPackageDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
+ gid_t gid) {
bs::error_code error;
bf::perms perms = bf::owner_read |
bf::owner_write |
- bf::group_read |
- bf::others_read;
- if (bf::is_directory(subpath))
+ bf::group_read;
+ // symlink will be skipped
+ if (bf::is_symlink(symlink_status(subpath)))
+ return true;
+
+ // non directory will be skipped
+ bool result = true;
+ if (bf::is_directory(subpath)) {
perms |= bf::owner_exe | bf::group_exe | bf::others_exe;
+ result = SetOwnerAndPermissions(subpath, uid, gid, perms);
+ }
- return SetOwnerAndPermissions(subpath, GLOBAL_USER,
- tzplatform_getgid(TZ_SYS_GLOBALAPP_USER),
- perms);
+ return result;
}
bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
return list;
}
+bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
+ std::vector<char*> rofiles;
+ for (auto& entry : kReadOnlyEntries)
+ rofiles.push_back(strdup(entry));
+
+ for (bf::directory_iterator file(src_dir);
+ file != bf::directory_iterator();
+ ++file) {
+ if (bf::is_regular_file(file->path())) {
+ bf::path current(file->path());
+ bf::path file_name = current.filename();
+ LOG(DEBUG) << "file_name: " << file_name;
+ rofiles.push_back(strdup(file_name.c_str()));
+ }
+ }
+
+ bs::error_code error;
+ for (auto& entry : rofiles) {
+ bf::path src_path = src_dir / entry;
+ bf::path dst_path = dst_dir / entry;
+ free(const_cast<char*>(entry));
+ if (!bf::exists(src_path)) {
+ // check if symlink for .mmc/bin,lib,res, then do not skip
+ if (!bf::is_symlink(symlink_status(src_path))) {
+ LOG(ERROR) << "src_path not exist : " << src_path;
+ continue;
+ }
+ }
+ if (bf::exists(dst_path)) {
+ LOG(WARNING) << "dst_path exist, skip : " << dst_path;
+ continue;
+ }
+ bf::create_symlink(src_path, dst_path, error);
+ if (error) {
+ LOG(ERROR) << "Symlink creation failure src_path: " << src_path
+ << " dst_path: " << dst_path;
+ LOG(ERROR) << "error: " << error.message();
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
+ bs::error_code error;
+ for (bf::directory_iterator file(dst_dir);
+ file != bf::directory_iterator();
+ ++file) {
+ bf::path current(file->path());
+ if (bf::is_symlink(symlink_status(current))) {
+ bf::path resolved_path = bf::read_symlink(current, error);
+ if (error) {
+ LOG(ERROR) << "Getting resolved path of symlink: " << current;
+ LOG(ERROR) << "resolved_path: " << resolved_path;
+ LOG(ERROR) << "error: " << error.message();
+ return false;
+ }
+ LOG(DEBUG) << "resolved_path: " << resolved_path;
+ bf::path parent = resolved_path.parent_path();
+ if (!parent.empty() && (parent == src_dir)) {
+ bf::remove(current, error);
+ LOG(DEBUG) << "removed: " << current;
+ if (error) {
+ LOG(ERROR) << "Symlink deletion failure for: " << current;
+ LOG(ERROR) << "error: " << error.message();
+ return false;
+ }
+ } else {
+ LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
+ << parent << ")";
+ }
+ }
+ }
+ bf::path shared_res = dst_dir / kSharedResDir;
+ if (bf::is_symlink(symlink_status(shared_res))) {
+ bf::remove(shared_res, error);
+ if (error) {
+ LOG(ERROR) << "Symlink deletion failure for: " << shared_res;
+ LOG(ERROR) << "error: " << error.message();
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace
namespace common_installer {
bool CreateSkelDirectories(const std::string& pkgid,
const std::string& api_version,
- bool trusted) {
+ bool trusted, bool is_preload) {
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 false;
}
- return true;
+ bool result = true;
+ if (!is_preload) {
+ bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+ result = CreateSymlinkFiles(src_dir, path);
+ }
+
+ return result;
}
bool CopyUserDirectories(const std::string& pkgid) {
user_list list = GetUserList();
for (auto l : list) {
- LOG(DEBUG) << "Copying directories for uid: " << std::get<0>(l);
+ uid_t uid = std::get<0>(l);
+ LOG(DEBUG) << "Copying directories for uid: " << uid;
bf::path apps_rw(std::get<2>(l) / "apps_rw");
bf::path src = bf::path(kSkelAppDir) / pkgid;
bf::path dst = apps_rw / pkgid;
- if (!ci::CopyDir(src, dst))
+ if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, true))
continue;
- if (!SetPackageDirectoryOwnerAndPermissions(dst, std::get<0>(l),
- std::get<1>(l)))
+ gid_t gid = std::get<1>(l);
+ if (!SetPackageDirectoryOwnerAndPermissions(dst, uid, gid))
return false;
for (bf::recursive_directory_iterator iter(dst);
iter != bf::recursive_directory_iterator(); ++iter) {
if (!SetPackageDirectoryOwnerAndPermissions(iter->path(),
- std::get<0>(l), std::get<1>(l)))
+ uid, gid))
return false;
}
std::string error_message;
return true;
}
-bool CreateLegacyDirectories(const std::string& pkgid) {
- // create lagcay directories for backward compatibility
- bs::error_code error;
- bf::path path = bf::path(kLegacyAppDir) / pkgid;
- bf::create_directories(path, error);
- if (error && !bf::exists(path)) {
- LOG(ERROR) << "Failed to create directory: " << path;
+bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+ bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+ if (!bf::exists(src_dir)) {
+ LOG(ERROR) << "src_dir not exists";
return false;
}
- std::vector<const char*> dirs(kEntries);
- dirs.push_back(kSharedTrustedDir);
- dirs.push_back(kSharedDataDir);
- for (auto& entry : dirs) {
- bf::path subpath = path / entry;
- bf::create_directories(subpath, error);
- if (error && !bf::exists(subpath)) {
- LOG(ERROR) << "Failed to create directory: " << subpath;
- return false;
- }
- if (!SetLegacyDirectoryOwnerAndPermissions(subpath)) {
- LOG(ERROR) << "Failed to set permission: " << subpath;
- return false;
+ bool result = true;
+ user_list list = GetUserList();
+ for (auto l : list) {
+ uid_t uid = std::get<0>(l);
+ LOG(DEBUG) << "Creating symlinks for uid: " << uid;
+ // check installed user private app.
+ if (QueryIsPackageInstalled(pkgid, uid))
+ continue;
+ bf::path apps_rw(std::get<2>(l) / "apps_rw");
+ bf::path dst_dir = apps_rw / pkgid;
+ if (!bf::exists(dst_dir)) {
+ LOG(WARNING) << "dst_dir not exists";
+ continue;
}
+ result = CreateSymlinkFiles(src_dir, dst_dir);
}
+ return result;
+}
- std::string error_message;
- if (!RegisterSecurityContextForPath(pkgid, path, GLOBAL_USER,
- false, &error_message)) {
- LOG(ERROR) << "Failed to register security context for path: " << path
- << ", error_message: " << error_message;
+bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+ bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+ if (!bf::exists(src_dir)) {
+ LOG(ERROR) << "src_dir not exists";
return false;
}
- return true;
+ tzplatform_set_user(uid);
+ bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+ tzplatform_reset_user();
+ if (!bf::exists(dst_dir)) {
+ LOG(WARNING) << "dst_dir not exists";
+ return true;
+ }
+ bool result = CreateSymlinkFiles(src_dir, dst_dir);
+
+ return result;
}
-bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid) {
- bool del_flag = true;
- uid_t chk_uid;
+bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
+ bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+ if (!bf::exists(src_dir)) {
+ LOG(ERROR) << "src_dir not exists";
+ return false;
+ }
+ bool result = true;
user_list list = GetUserList();
- if (list.empty())
- return true;
for (auto l : list) {
- chk_uid = std::get<0>(l);
- if (chk_uid == uid)
+ uid_t uid = std::get<0>(l);
+ LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
+ // check installed user private app.
+ if (QueryIsPackageInstalled(pkgid, uid))
+ continue;
+ bf::path apps_rw(std::get<2>(l) / "apps_rw");
+ bf::path dst_dir = apps_rw / pkgid;
+ if (!bf::exists(dst_dir)) {
+ LOG(WARNING) << "dst_dir not exists";
continue;
- LOG(DEBUG) << "Check package existence for uid: " << chk_uid;
- if (QueryIsPackageInstalled(pkgid, chk_uid)) {
- LOG(DEBUG) << "Package: " << pkgid << " for uid: " << chk_uid
- << " still exists.";
- del_flag = false;
- break;;
}
+ result = DeleteSymlinkFiles(src_dir, dst_dir);
}
+ return result;
+}
- if (del_flag && uid != GLOBAL_USER) {
- if (QueryIsPackageInstalled(pkgid, GLOBAL_USER)) {
- LOG(DEBUG) << "Package: " << pkgid << " for uid: " << GLOBAL_USER
- << " still exists.";
- del_flag = false;
- }
+bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
+ bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
+ if (!bf::exists(src_dir)) {
+ LOG(ERROR) << "src_dir not exists";
+ return false;
}
- if (del_flag) {
- LOG(DEBUG) << "Delete legacy directories for package: " << pkgid;
- DeleteDirectories(bf::path(kLegacyAppDir), pkgid);
+ tzplatform_set_user(uid);
+ bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
+ tzplatform_reset_user();
+ if (!bf::exists(dst_dir)) {
+ LOG(WARNING) << "dst_dir not exists";
+ return true;
}
-
- return true;
+ bool result = DeleteSymlinkFiles(src_dir, dst_dir);
+ return result;
}
} // namespace common_installer
* \param pkgid package id
* \param api_version package api version
* \param trusted signed package flag
+ * \param is_preload preload flag
*
* \return bool true if succeed, false otherwise
*
*/
bool CreateSkelDirectories(const std::string& pkgid,
const std::string& api_version,
- bool trusted);
+ bool trusted, bool is_preload);
/**
* \brief Performs deletion of directories
std::string GetDirectoryPathForExternalStorage();
/**
- * \brief Create Legacy directories
+ * \brief Create symlinks for read-only files of global app for all users.
*
+ * \param pkgid package id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid);
+
+/**
+ * \brief Create symlinks for read-only files of global app for user.
+ *
+ * \param pkgid package id
* \param uid user id
+ *
+ * \return true if succeed, false otherwise
+ *
+ */
+bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
+
+/**
+ * \brief Delete symlinks for read-only files of global app for all users.
+ *
* \param pkgid package id
*
* \return true if succeed, false otherwise
*
*/
-bool CreateLegacyDirectories(const std::string& pkgid);
+bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid);
/**
- * \brief Delete Legacy directories
+ * \brief Delete symlinks for read-only files of global app for user.
*
* \param pkgid package id
+ * \param uid user id
*
* \return true if succeed, false otherwise
*
*/
-bool DeleteLegacyDirectories(uid_t uid, const std::string& pkgid);
+bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid);
} // namespace common_installer
LOG(ERROR) << "Fail to backup package directory of: " << iter->path();
return false;
}
- } else if (bf::is_symlink(iter->path())) {
+ } else if (bf::is_symlink(symlink_status(iter->path()))) {
bs::error_code error;
bf::copy_symlink(iter->path(), to / iter->path().filename(), error);
if (error) {
return Step::Status::PARSE_ERROR;
}
- // TODO(jongmyeongko): check package features...
- // Implementation of this need more consideration (offline mode and store app)
-
if (manifest_location_ == ManifestLocation::INSTALLED) {
// recovery of tep value for installed package
std::string old_tep =
--- /dev/null
+// 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/step/filesystem/step_create_globalapp_symlinks.h"
+
+#include <string>
+
+#include "common/pkgdir_tool_request.h"
+#include "common/shared_dirs.h"
+#include "common/pkgmgr_query.h"
+
+namespace common_installer {
+namespace filesystem {
+
+common_installer::Step::Status StepCreateGlobalAppSymlinks::process() {
+ if (context_->is_preload_request.get())
+ return Step::Status::OK;
+ std::string package_id = context_->pkgid.get();
+
+ if (context_->request_type.get() == RequestType::Uninstall) {
+ if ((context_->request_mode.get() == RequestMode::USER) &&
+ QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER)) {
+ LOG(INFO) << "Creating globalapp symlinks for current user, package: "
+ << package_id;
+ if (!RequestCreateGlobalAppSymlinksForUser(package_id,
+ context_->uid.get())) {
+ LOG(ERROR) << "Failed to create globalapp symlinks";
+ return Status::GLOBALSYMLINK_ERROR;
+ }
+ }
+ } else {
+ if (context_->request_mode.get() == RequestMode::GLOBAL) {
+ LOG(INFO) << "Creating globalapp symlinks for all user, package: "
+ << package_id;
+ if (!RequestCreateGlobalAppSymlinks(package_id)) {
+ LOG(ERROR) << "Failed to create globalapp symlinks";
+ return Status::GLOBALSYMLINK_ERROR;
+ }
+ }
+ }
+
+ return Status::OK;
+}
+
+} // namespace filesystem
+} // namespace common_installer
--- /dev/null
+// 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_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
+#define COMMON_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Installation.
+ * Responsible for creating symlinks for read-only files of globalapp
+ * for backward compatibility. (wgt/tpk)
+ *
+ * * process method implements creation of symlinks under RW app_root per user.
+ *
+ * * Other methods are empty.
+ */
+class StepCreateGlobalAppSymlinks : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ Status process() override;
+ Status clean() override { return Status::OK; }
+ Status undo() override { return Status::OK; }
+ Status precheck() override { return Status::OK; }
+
+ STEP_NAME(CreateGlobalAppSymlinks)
+};
+
+} // namespace filesystem
+} // namespace common_installer
+
+#endif // COMMON_STEP_FILESYSTEM_STEP_CREATE_GLOBALAPP_SYMLINKS_H_
trusted = true;
if (!common_installer::CreateSkelDirectories(package_id,
- str_ver, trusted)) {
+ str_ver, trusted, context_->is_preload_request.get())) {
LOG(ERROR) << "Failed to create skel dirs";
return Status::APP_DIR_ERROR;
}
void RemoveBinarySymlinks(const bf::path& dir) {
for (bf::directory_iterator iter(dir / kBinaryDir);
iter != bf::directory_iterator(); ++iter) {
- if (bf::is_symlink(iter->path())) {
+ if (bf::is_symlink(symlink_status(iter->path()))) {
// FIXME: note that this assumes that it is not possible to create
// explicitly symlinks in bin/ directory pointing to whatever
bs::error_code error;
namespace bf = boost::filesystem;
namespace {
-const char kSharedRes[] = "shared/res";
+
bool SkipDirectoryIfGlobal(const bf::path& path) {
static const std::vector<std::string> dirs_to_ignore = {
{"cache"},
return std::find(dirs_to_ignore.begin(), dirs_to_ignore.end(), path) !=
dirs_to_ignore.end();
}
+
} // namespace
if (context_->external_storage)
context_->external_storage->Commit();
- // If global package, then some RW directories won't be removed here,
- // instead, following StepRemoveLegacyDirectories will check and remove them.
- if (QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER) ||
- context_->uid.get() == GLOBAL_USER) {
+ if (QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER)) {
for (bf::directory_iterator itr(pkg_path); itr != bf::directory_iterator();
++itr) {
- if (bf::is_directory(itr->status())) {
+ if (bf::is_symlink(symlink_status(itr->path()))) {
+ // for removing symlink to .mmc/bin,lib,res
+ bf::remove_all(itr->path(), error);
+ } else if (bf::is_directory(itr->status())) {
if (SkipDirectoryIfGlobal(itr->path().leaf())) {
LOG(DEBUG) << "Skipping remove dir:" << itr->path().c_str();
continue;
bf::remove_all(itr->path(), error);
}
}
- // The shared/res will be removed if it exists.
- bf::path shared_res_path = pkg_path / kSharedRes;
- bf::remove_all(shared_res_path, error);
} else {
bf::remove_all(pkg_path, error);
if (error) {
--- /dev/null
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/step/filesystem/step_remove_globalapp_symlinks.h"
+
+#include <string>
+
+#include "common/installer_context.h"
+#include "common/pkgdir_tool_request.h"
+#include "common/pkgmgr_query.h"
+
+namespace common_installer {
+namespace filesystem {
+
+Step::Status StepRemoveGlobalAppSymlinks::process() {
+ if (context_->is_preload_request.get())
+ return Step::Status::OK;
+
+ if (!QueryIsPackageInstalled(context_->pkgid.get(), GLOBAL_USER))
+ return Step::Status::OK;
+
+ std::string package_id = context_->pkgid.get();
+
+ if (context_->request_type.get() == RequestType::Uninstall) {
+ if (context_->request_mode.get() == RequestMode::GLOBAL) {
+ LOG(INFO) << "Deleting globalapp symlinks for all user, package: "
+ << package_id;
+ if (!RequestDeleteGlobalAppSymlinks(package_id)) {
+ LOG(ERROR) << "Failed to delete globalapp symlinks";
+ return Status::GLOBALSYMLINK_ERROR;
+ }
+ }
+ } else {
+ LOG(INFO) << "Deleting globalapp symlinks for current user, package: "
+ << package_id;
+ if (!RequestDeleteGlobalAppSymlinksForUser(package_id,
+ context_->uid.get())) {
+ LOG(ERROR) << "Failed to delete globalapp symlinks";
+ return Status::GLOBALSYMLINK_ERROR;
+ }
+ }
+
+ return Step::Status::OK;
+}
+
+} // namespace filesystem
+} // namespace common_installer
+
--- /dev/null
+// 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_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
+#define COMMON_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace filesystem {
+
+/**
+ * \brief Uninstallation.
+ * Responsible for removing symlink files for read-only files of globalapp
+ * for backward compatibility. (wgt/tpk)
+ *
+ * * process method implements removal of symlinks under RW app_root per user.
+ *
+ * * Other methods are empty.
+ *
+ */
+
+class StepRemoveGlobalAppSymlinks : public common_installer::Step {
+ public:
+ using Step::Step;
+
+ Status process() override;
+ Status clean() override { return Status::OK; }
+ Status undo() override { return Status::OK; }
+ Status precheck() override { return Status::OK; }
+
+ STEP_NAME(RemoveGlobalAppSymlinks)
+};
+
+} // namespace filesystem
+} // namespace common_installer
+
+#endif // COMMON_STEP_FILESYSTEM_STEP_REMOVE_GLOBALAPP_SYMLINKS_H_
public:
/** Possible code returned by process, undo, clean, precheck methods. */
enum class Status {
+ GLOBALSYMLINK_ERROR = -26, // TODO(jongmyeong.ko)
GRANT_PERMISSION_ERROR = PKGCMD_ERRCODE_GRANT_PERMISSION_ERROR,
IMAGE_ERROR = PKGCMD_ERRCODE_IMAGE_ERROR,
UNZIP_ERROR = PKGCMD_ERRCODE_UNZIP_ERROR,
return true;
}
-bool CopyDir(const bf::path& src, const bf::path& dst, FSFlag flags) {
+bool CopyDir(const bf::path& src, const bf::path& dst,
+ FSFlag flags, bool skip_symlink) {
try {
// Check whether the function call is valid
if (!bf::exists(src) || !bf::is_directory(src)) {
try {
bf::path current(file->path());
bf::path target = dst / current.filename();
- if (bf::is_directory(current)) {
- // Found directory: Recursion
- if (!CopyDir(current, target, flags)) {
- return false;
- }
- } else if (bf::is_symlink(current)) {
+
+ if (bf::is_symlink(symlink_status(current))) {
+ if (skip_symlink)
+ continue;
if ((flags & FS_MERGE_DIRECTORIES) && bf::exists(target))
continue;
bf::copy_symlink(current, target);
+ } else if (bf::is_directory(current)) {
+ // Found directory: Recursion
+ if (!CopyDir(current, target, flags, skip_symlink)) {
+ return false;
+ }
} else {
if ((flags & FS_MERGE_DIRECTORIES) && bf::exists(target))
continue;
bf::rename(src, dst, error);
if (error) {
LOG(WARNING) << "Cannot move directory: " << src << ". Will copy/remove...";
- if (!CopyDir(src, dst, flags)) {
+ if (!CopyDir(src, dst, flags, false)) {
LOG(ERROR) << "Cannot copy directory: " << src;
return false;
}
bool CreateDir(const boost::filesystem::path& path);
bool CopyDir(const boost::filesystem::path& src,
- const boost::filesystem::path& dst, FSFlag flags = FS_NONE);
+ const boost::filesystem::path& dst,
+ FSFlag flags = FS_NONE, bool skip_symlink = false);
bool CopyFile(const boost::filesystem::path& src,
const boost::filesystem::path& dst);
" <arg type='s' name='pkgid' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
- " <method name='CreateLegacyDirs'>"
+ " <method name='CreateExternalDirsForAllPkgs'>"
+ " <arg type='b' name='result' direction='out'/>"
+ " </method>"
+ " <method name='CreateGlobalAppSymlinks'>"
" <arg type='s' name='pkgid' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
- " <method name='DeleteLegacyDirs'>"
+ " <method name='DeleteGlobalAppSymlinks'>"
" <arg type='s' name='pkgid' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
- " <method name='CreateExternalDirsForAllPkgs'>"
+ " <method name='CreateGlobalAppSymlinksForUser'>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='uid' direction='in'/>"
+ " <arg type='b' name='result' direction='out'/>"
+ " </method>"
+ " <method name='DeleteGlobalAppSymlinksForUser'>"
+ " <arg type='s' name='pkgid' direction='in'/>"
+ " <arg type='i' name='uid' direction='in'/>"
" <arg type='b' name='result' direction='out'/>"
" </method>"
" </interface>"
gpointer user_data);
void OnBusAcquired(GDBusConnection* connection, const gchar* name,
gpointer user_data);
- int GetSenderUnixId(GDBusConnection *connection, const gchar* sender);
GDBusNodeInfo* node_info_;
guint owner_id_;
this);
}
-int PkgdirToolService::GetSenderUnixId(GDBusConnection* connection,
- const gchar* sender) {
- int uid = -1;
-
- GDBusMessage* msg = nullptr;
- msg = g_dbus_message_new_method_call("org.freedesktop.DBus",
- "/org/freedesktop/DBus",
- "org.freedesktop.DBus",
- "GetConnectionUnixUser");
- if (!msg) {
- LOG(ERROR) << "Failed to setup dbus message";
- return -1;
- }
- g_dbus_message_set_body(msg, g_variant_new("(s)", sender));
-
- GError* err = nullptr;
- GDBusMessage* reply = nullptr;
- reply = g_dbus_connection_send_message_with_reply_sync(connection, msg,
- G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, nullptr, nullptr, &err);
- if (!reply) {
- LOG(ERROR) << "Failed to send dbus message";
- if (err) {
- LOG(ERROR) << "error message: " << err->message;
- g_error_free(err);
- }
- g_object_unref(msg);
- return -1;
- }
-
- GVariant* body = g_dbus_message_get_body(reply);
- g_variant_get(body, "(u)", &uid);
-
- g_object_unref(msg);
- g_object_unref(reply);
-
- return uid;
-}
-
void PkgdirToolService::HandleMethodCall(GDBusConnection* connection,
const gchar* sender, const gchar* object_path, const gchar* interface_name,
const gchar* method_name, GVariant* parameters,
GDBusMethodInvocation* invocation, gpointer user_data) {
+ UNUSED(connection);
+ UNUSED(sender);
UNUSED(object_path);
UNUSED(interface_name);
UNUSED(user_data);
} else if (g_strcmp0(method_name, "DeleteExternalDirs") == 0) {
g_variant_get(parameters, "(&s)", &val);
r = ci::PerformExternalDirectoryDeletionForAllUsers(std::string(val));
- } else if (g_strcmp0(method_name, "CreateLegacyDirs") == 0) {
- g_variant_get(parameters, "(&s)", &val);
- r = ci::CreateLegacyDirectories(std::string(val));
- } else if (g_strcmp0(method_name, "DeleteLegacyDirs") == 0) {
- g_variant_get(parameters, "(&s)", &val);
- int sender_uid = GetSenderUnixId(connection, sender);
- if (sender_uid < 0) {
- LOG(ERROR) << "Failed to get sender_uid: " << sender_uid;
- } else {
- r = ci::DeleteLegacyDirectories((uid_t)sender_uid, std::string(val));
- }
} else if (g_strcmp0(method_name, "CreateExternalDirsForAllPkgs") == 0) {
r = ci::PerformExternalDirectoryCreationForAllPkgs();
+ } else if (g_strcmp0(method_name, "CreateGlobalAppSymlinks") == 0) {
+ g_variant_get(parameters, "(&s)", &val);
+ r = ci::CreateGlobalAppSymlinksForAllUsers(std::string(val));
+ } else if (g_strcmp0(method_name, "DeleteGlobalAppSymlinks") == 0) {
+ g_variant_get(parameters, "(&s)", &val);
+ r = ci::DeleteGlobalAppSymlinksForAllUsers(std::string(val));
+ } else if (g_strcmp0(method_name, "CreateGlobalAppSymlinksForUser") == 0) {
+ uid_t uid;
+ g_variant_get(parameters, "(&si)", &val, &uid);
+ r = ci::CreateGlobalAppSymlinksForUser(std::string(val), uid);
+ } else if (g_strcmp0(method_name, "DeleteGlobalAppSymlinksForUser") == 0) {
+ uid_t uid;
+ g_variant_get(parameters, "(&si)", &val, &uid);
+ r = ci::DeleteGlobalAppSymlinksForUser(std::string(val), uid);
} else {
LOG(ERROR) << "Unknown method call: " << method_name;
}