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>
13 #include "common/utils/byte_size_literals.h"
14 #include "common/utils/file_util.h"
15 #include "common/utils/request.h"
17 namespace fs = std::filesystem;
21 const char kWgtType[] = "wgt";
22 const char kExternalDirForWgt[] = "res";
24 const std::vector<std::string> kExternalDirsForTpk = {
30 int64_t SizeInMB(int64_t size) {
31 return (size + 1_MB - 1) / 1_MB;
34 void ClearApp2ExtDirDetail(gpointer data) {
35 app2ext_dir_details* dir_detail =
36 reinterpret_cast<app2ext_dir_details*>(data);
38 free(dir_detail->name);
44 namespace common_installer {
46 ExternalStorage::ExternalStorage(RequestType type,
47 const std::string& pkgid, const std::string& package_type,
48 const fs::path& application_root, uid_t uid)
51 package_type_(package_type),
52 application_root_(application_root),
56 if (package_type_ == kWgtType)
57 external_dirs_.push_back(kExternalDirForWgt);
59 external_dirs_ = kExternalDirsForTpk;
62 ExternalStorage::ExternalStorage(RequestType type,
63 const std::string& pkgid, const std::string& package_type,
64 const fs::path& application_root, uid_t uid,
65 bool is_external_move)
68 package_type_(package_type),
69 application_root_(application_root),
72 if (package_type_ == kWgtType)
73 external_dirs_.push_back(kExternalDirForWgt);
75 external_dirs_ = kExternalDirsForTpk;
78 move_type_ = APP2EXT_MOVE_TO_EXT;
80 move_type_ = APP2EXT_MOVE_TO_PHONE;
83 ExternalStorage::ExternalStorage(RequestType type,
84 const std::string& pkgid, uid_t uid)
92 ExternalStorage::~ExternalStorage() {
95 bool ExternalStorage::Finalize(bool success) {
96 int ret = APP2EXT_STATUS_SUCCESS;
98 case RequestType::Install:
99 ret = handle_->interface.client_usr_post_install(pkgid_.c_str(),
100 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
102 case RequestType::Update:
103 case RequestType::Delta:
104 ret = handle_->interface.client_usr_post_upgrade(pkgid_.c_str(),
105 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
107 case RequestType::Uninstall:
108 ret = handle_->interface.client_usr_post_uninstall(pkgid_.c_str(), uid_);
110 case RequestType::Move:
111 ret = handle_->interface.client_usr_post_move(pkgid_.c_str(),
112 static_cast<app2ext_move_type_t>(move_type_),
115 case RequestType::MigrateExtImg:
116 ret = handle_->interface.client_usr_post_migrate_legacy(pkgid_.c_str(),
120 LOG(ERROR) << "Not supported installation mode ("
121 << GetRequestTypeString(type_) << ")";
123 return ret == APP2EXT_STATUS_SUCCESS;
126 bool ExternalStorage::Commit() {
127 return Finalize(true);
130 bool ExternalStorage::Abort() {
131 return Finalize(false);
134 const std::vector<std::string>& ExternalStorage::external_dirs() const {
135 return external_dirs_;
138 bool ExternalStorage::Initialize(
139 const fs::path& space_requirement) {
140 // external size in MB, set any-non zero size as default
141 int external_size = 1;
143 if (!space_requirement.empty()) {
144 if (package_type_ != kWgtType) {
145 for (auto& dir : kExternalDirsForTpk) {
146 fs::path requirement = space_requirement / dir;
147 if (!fs::exists(requirement))
150 SizeInMB(GetDirectorySize(requirement));
153 // for wgt whole content of package goes to res/
155 SizeInMB(GetDirectorySize(space_requirement));
159 handle_ = service.getInterfaceHandle();
161 LOG(ERROR) << "app2ext_init() failed";
165 GList* glist = nullptr;
166 for (auto& dir : external_dirs_) {
167 app2ext_dir_details* dir_detail = reinterpret_cast<app2ext_dir_details*>(
168 calloc(1, sizeof(app2ext_dir_details)));
170 LOG(ERROR) << "Out of memory";
171 g_list_free_full(glist, &ClearApp2ExtDirDetail);
174 dir_detail->name = strdup(dir.c_str());
175 if (!dir_detail->name) {
176 LOG(ERROR) << "Out of memory";
178 g_list_free_full(glist, &ClearApp2ExtDirDetail);
181 dir_detail->type = APP2EXT_DIR_RO;
182 glist = g_list_append(glist, dir_detail);
187 case RequestType::Install:
188 ret = handle_->interface.client_usr_force_clean(pkgid_.c_str(), uid_);
190 LOG(ERROR) << "force_clean failed";
193 ret = handle_->interface.client_usr_pre_install(pkgid_.c_str(), glist,
194 external_size, uid_);
196 case RequestType::Update:
197 case RequestType::Delta:
198 ret = handle_->interface.client_usr_pre_upgrade(pkgid_.c_str(), glist,
199 external_size, uid_);
201 case RequestType::Move:
202 if (move_type_ == -1) {
203 LOG(ERROR) << "Invalid request [" << move_type_ << "]";
208 // try umount before move
209 ret = handle_->interface.client_usr_disable(pkgid_.c_str(), uid_);
211 ret = handle_->interface.client_usr_pre_move(pkgid_.c_str(), glist,
212 static_cast<app2ext_move_type_t>(move_type_),
215 case RequestType::Uninstall:
216 ret = handle_->interface.client_usr_pre_uninstall(pkgid_.c_str(), uid_);
218 case RequestType::MigrateExtImg:
219 ret = handle_->interface.client_usr_pre_migrate_legacy(pkgid_.c_str(),
223 LOG(ERROR) << "Installation type (" << GetRequestTypeString(type_) << ")"
224 << " is not supported by external installation";
229 g_list_free_full(glist, &ClearApp2ExtDirDetail);
233 std::unique_ptr<ExternalStorage> ExternalStorage::MoveInstalledStorage(
234 RequestType type, const fs::path& application_root,
235 const std::string& pkgid, const std::string& package_type,
236 uid_t uid, bool is_external_move) {
238 std::unique_ptr<ExternalStorage> external_storage(
239 new ExternalStorage(type, pkgid, package_type, application_root, uid,
241 if (!external_storage->Initialize(application_root)) {
242 LOG(WARNING) << "Cannot initialize external storage for move";
246 return external_storage;
249 std::unique_ptr<ExternalStorage> ExternalStorage::AcquireExternalStorage(
250 RequestType type, const fs::path& application_root,
251 const std::string& pkgid, const std::string& package_type,
252 const fs::path& space_requirement,
254 std::unique_ptr<ExternalStorage> external_storage(
255 new ExternalStorage(type, pkgid, package_type, application_root, uid));
256 if (!external_storage->Initialize(space_requirement)) {
257 LOG(WARNING) << "Cannot initialize external storage for request";
260 return external_storage;
263 std::unique_ptr<ExternalStorage> ExternalStorage::MigrateExternalStorage(
264 RequestType type, const std::string& pkgid, uid_t uid) {
265 std::unique_ptr<ExternalStorage> external_storage(
266 new ExternalStorage(type, pkgid, uid));
267 fs::path empty_path("");
268 if (!external_storage->Initialize(empty_path)) {
269 LOG(WARNING) << "Cannot initialize external storage for request";
272 return external_storage;
275 } // namespace common_installer