1 // Copyright (c) 2015 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/external_storage.h"
9 #include <manifest_parser/utils/logging.h>
11 #include "common/utils/byte_size_literals.h"
12 #include "common/utils/file_util.h"
14 namespace bf = boost::filesystem;
18 const char kWgtType[] = "wgt";
19 const char kExternalDirForWgt[] = "res";
21 const std::vector<std::string> kExternalDirsForTpk = {
27 int64_t SizeInMB(int64_t size) {
28 return (size + 1_MB - 1) / 1_MB;
33 namespace common_installer {
35 ExternalStorage::ExternalStorage(RequestType type,
36 const std::string& pkgid, const std::string& package_type,
37 const boost::filesystem::path& application_root, uid_t uid)
40 package_type_(package_type),
41 application_root_(application_root),
44 if (package_type_ == kWgtType) {
45 external_dirs_.push_back(kExternalDirForWgt);
47 external_dirs_ = kExternalDirsForTpk;
52 ExternalStorage::ExternalStorage(RequestType type,
53 const std::string& pkgid, const std::string& package_type,
54 const boost::filesystem::path& application_root, uid_t uid,
55 bool is_external_move)
58 package_type_(package_type),
59 application_root_(application_root),
62 if (package_type_ == kWgtType) {
63 external_dirs_.push_back(kExternalDirForWgt);
65 external_dirs_ = kExternalDirsForTpk;
68 move_type_ = APP2EXT_MOVE_TO_EXT;
70 move_type_ = APP2EXT_MOVE_TO_PHONE;
73 ExternalStorage::ExternalStorage(RequestType type,
74 const std::string& pkgid, uid_t uid)
81 ExternalStorage::~ExternalStorage() {
83 app2ext_deinit(handle_);
86 bool ExternalStorage::Finalize(bool success) {
87 int ret = APP2EXT_STATUS_SUCCESS;
89 case RequestType::Install:
90 ret = handle_->interface.client_usr_post_install(pkgid_.c_str(),
91 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
93 case RequestType::Update:
94 case RequestType::Delta:
95 ret = handle_->interface.client_usr_post_upgrade(pkgid_.c_str(),
96 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
98 case RequestType::Uninstall:
99 ret = handle_->interface.client_usr_post_uninstall(pkgid_.c_str(), uid_);
101 case RequestType::Move:
102 ret = handle_->interface.client_usr_post_move(pkgid_.c_str(),
103 static_cast<app2ext_move_type_t>(move_type_),
106 case RequestType::MigrateExtImg:
107 ret = handle_->interface.client_usr_post_migrate_legacy(pkgid_.c_str(),
111 assert(false && "Not supported installation mode");
113 return ret == APP2EXT_STATUS_SUCCESS;
116 bool ExternalStorage::Commit() {
117 return Finalize(true);
120 bool ExternalStorage::Abort() {
121 return Finalize(false);
124 const std::vector<std::string>& ExternalStorage::external_dirs() const {
125 return external_dirs_;
128 bool ExternalStorage::Initialize(
129 const boost::filesystem::path& space_requirement) {
130 // external size in MB, set any-non zero size as default
131 int external_size = 1;
133 if (!space_requirement.empty()) {
134 if (package_type_ != kWgtType) {
135 for (auto& dir : kExternalDirsForTpk) {
136 bf::path requirement = space_requirement / dir;
137 if (!bf::exists(requirement))
140 SizeInMB(GetDirectorySize(requirement));
143 // for wgt whole content of package goes to res/
145 SizeInMB(GetDirectorySize(space_requirement));
149 if (external_size == 0)
152 handle_ = app2ext_init(APP2EXT_SD_CARD);
154 LOG(ERROR) << "app2ext_init() failed";
158 GList* glist = nullptr;
159 for (auto& dir : external_dirs_) {
160 app2ext_dir_details* dir_detail = reinterpret_cast<app2ext_dir_details*>(
161 calloc(1, sizeof(app2ext_dir_details)));
162 dir_detail->name = strdup(dir.c_str());
163 dir_detail->type = APP2EXT_DIR_RO;
164 glist = g_list_append(glist, dir_detail);
169 case RequestType::Install:
170 ret = handle_->interface.client_usr_force_clean(pkgid_.c_str(), uid_);
172 LOG(ERROR) << "force_clean failed";
175 ret = handle_->interface.client_usr_pre_install(pkgid_.c_str(), glist,
176 external_size, uid_);
178 case RequestType::Update:
179 case RequestType::Delta:
180 ret = handle_->interface.client_usr_pre_upgrade(pkgid_.c_str(), glist,
181 external_size, uid_);
183 case RequestType::Move:
184 if (move_type_ == -1) {
185 LOG(ERROR) << "Invalid request [" << move_type_ << "]";
190 // try umount before move
191 ret = handle_->interface.client_usr_disable(pkgid_.c_str(), uid_);
193 ret = handle_->interface.client_usr_pre_move(pkgid_.c_str(), glist,
194 static_cast<app2ext_move_type_t>(move_type_),
197 case RequestType::Uninstall:
198 ret = handle_->interface.client_usr_pre_uninstall(pkgid_.c_str(), uid_);
200 case RequestType::MigrateExtImg:
201 ret = handle_->interface.client_usr_pre_migrate_legacy(pkgid_.c_str(),
204 case RequestType::Reinstall:
205 case RequestType::Recovery:
206 case RequestType::ManifestDirectInstall:
207 case RequestType::ManifestDirectUpdate:
208 case RequestType::MountInstall:
209 case RequestType::MountUpdate:
210 LOG(ERROR) << "Installation type is not supported by external installation";
214 assert(false && "Invalid installation mode");
217 g_list_free_full(glist, [](gpointer data) {
218 app2ext_dir_details* dir_detail =
219 reinterpret_cast<app2ext_dir_details*>(data);
220 free(dir_detail->name);
226 std::unique_ptr<ExternalStorage> ExternalStorage::MoveInstalledStorage(
227 RequestType type, const boost::filesystem::path& application_root,
228 const std::string& pkgid, const std::string& package_type,
229 uid_t uid, bool is_external_move) {
231 std::unique_ptr<ExternalStorage> external_storage(
232 new ExternalStorage(type, pkgid, package_type, application_root, uid,
234 if (!external_storage->Initialize(application_root)) {
235 LOG(WARNING) << "Cannot initialize external storage for move";
239 return external_storage;
242 std::unique_ptr<ExternalStorage> ExternalStorage::AcquireExternalStorage(
243 RequestType type, const boost::filesystem::path& application_root,
244 const std::string& pkgid, const std::string& package_type,
245 const boost::filesystem::path& space_requirement,
247 std::unique_ptr<ExternalStorage> external_storage(
248 new ExternalStorage(type, pkgid, package_type, application_root, uid));
249 if (!external_storage->Initialize(space_requirement)) {
250 LOG(WARNING) << "Cannot initialize external storage for request";
253 return external_storage;
256 std::unique_ptr<ExternalStorage> ExternalStorage::MigrateExternalStorage(
257 RequestType type, const std::string& pkgid, uid_t uid) {
258 std::unique_ptr<ExternalStorage> external_storage(
259 new ExternalStorage(type, pkgid, uid));
260 bf::path empty_path("");
261 if (!external_storage->Initialize(empty_path)) {
262 LOG(WARNING) << "Cannot initialize external storage for request";
265 return external_storage;
268 } // namespace common_installer