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"
13 #include "common/utils/request.h"
15 namespace bf = boost::filesystem;
19 const char kWgtType[] = "wgt";
20 const char kExternalDirForWgt[] = "res";
22 const std::vector<std::string> kExternalDirsForTpk = {
28 int64_t SizeInMB(int64_t size) {
29 return (size + 1_MB - 1) / 1_MB;
32 void ClearApp2ExtDirDetail(gpointer data) {
33 app2ext_dir_details* dir_detail =
34 reinterpret_cast<app2ext_dir_details*>(data);
36 free(dir_detail->name);
42 namespace common_installer {
44 ExternalStorage::ExternalStorage(RequestType type,
45 const std::string& pkgid, const std::string& package_type,
46 const boost::filesystem::path& application_root, uid_t uid)
49 package_type_(package_type),
50 application_root_(application_root),
54 if (package_type_ == kWgtType)
55 external_dirs_.push_back(kExternalDirForWgt);
57 external_dirs_ = kExternalDirsForTpk;
60 ExternalStorage::ExternalStorage(RequestType type,
61 const std::string& pkgid, const std::string& package_type,
62 const boost::filesystem::path& application_root, uid_t uid,
63 bool is_external_move)
66 package_type_(package_type),
67 application_root_(application_root),
70 if (package_type_ == kWgtType)
71 external_dirs_.push_back(kExternalDirForWgt);
73 external_dirs_ = kExternalDirsForTpk;
76 move_type_ = APP2EXT_MOVE_TO_EXT;
78 move_type_ = APP2EXT_MOVE_TO_PHONE;
81 ExternalStorage::ExternalStorage(RequestType type,
82 const std::string& pkgid, uid_t uid)
90 ExternalStorage::~ExternalStorage() {
93 bool ExternalStorage::Finalize(bool success) {
94 int ret = APP2EXT_STATUS_SUCCESS;
96 case RequestType::Install:
97 ret = handle_->interface.client_usr_post_install(pkgid_.c_str(),
98 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
100 case RequestType::Update:
101 case RequestType::Delta:
102 ret = handle_->interface.client_usr_post_upgrade(pkgid_.c_str(),
103 success ? APP2EXT_STATUS_SUCCESS : APP2EXT_STATUS_FAILED, uid_);
105 case RequestType::Uninstall:
106 ret = handle_->interface.client_usr_post_uninstall(pkgid_.c_str(), uid_);
108 case RequestType::Move:
109 ret = handle_->interface.client_usr_post_move(pkgid_.c_str(),
110 static_cast<app2ext_move_type_t>(move_type_),
113 case RequestType::MigrateExtImg:
114 ret = handle_->interface.client_usr_post_migrate_legacy(pkgid_.c_str(),
118 LOG(ERROR) << "Not supported installation mode ("
119 << GetRequestTypeString(type_) << ")";
121 return ret == APP2EXT_STATUS_SUCCESS;
124 bool ExternalStorage::Commit() {
125 return Finalize(true);
128 bool ExternalStorage::Abort() {
129 return Finalize(false);
132 const std::vector<std::string>& ExternalStorage::external_dirs() const {
133 return external_dirs_;
136 bool ExternalStorage::Initialize(
137 const boost::filesystem::path& space_requirement) {
138 // external size in MB, set any-non zero size as default
139 int external_size = 1;
141 if (!space_requirement.empty()) {
142 if (package_type_ != kWgtType) {
143 for (auto& dir : kExternalDirsForTpk) {
144 bf::path requirement = space_requirement / dir;
145 if (!bf::exists(requirement))
148 SizeInMB(GetDirectorySize(requirement));
151 // for wgt whole content of package goes to res/
153 SizeInMB(GetDirectorySize(space_requirement));
157 handle_ = service.getInterfaceHandle();
159 LOG(ERROR) << "app2ext_init() failed";
163 GList* glist = nullptr;
164 for (auto& dir : external_dirs_) {
165 app2ext_dir_details* dir_detail = reinterpret_cast<app2ext_dir_details*>(
166 calloc(1, sizeof(app2ext_dir_details)));
168 LOG(ERROR) << "Out of memory";
169 g_list_free_full(glist, &ClearApp2ExtDirDetail);
172 dir_detail->name = strdup(dir.c_str());
173 if (!dir_detail->name) {
174 LOG(ERROR) << "Out of memory";
176 g_list_free_full(glist, &ClearApp2ExtDirDetail);
179 dir_detail->type = APP2EXT_DIR_RO;
180 glist = g_list_append(glist, dir_detail);
185 case RequestType::Install:
186 ret = handle_->interface.client_usr_force_clean(pkgid_.c_str(), uid_);
188 LOG(ERROR) << "force_clean failed";
191 ret = handle_->interface.client_usr_pre_install(pkgid_.c_str(), glist,
192 external_size, uid_);
194 case RequestType::Update:
195 case RequestType::Delta:
196 ret = handle_->interface.client_usr_pre_upgrade(pkgid_.c_str(), glist,
197 external_size, uid_);
199 case RequestType::Move:
200 if (move_type_ == -1) {
201 LOG(ERROR) << "Invalid request [" << move_type_ << "]";
206 // try umount before move
207 ret = handle_->interface.client_usr_disable(pkgid_.c_str(), uid_);
209 ret = handle_->interface.client_usr_pre_move(pkgid_.c_str(), glist,
210 static_cast<app2ext_move_type_t>(move_type_),
213 case RequestType::Uninstall:
214 ret = handle_->interface.client_usr_pre_uninstall(pkgid_.c_str(), uid_);
216 case RequestType::MigrateExtImg:
217 ret = handle_->interface.client_usr_pre_migrate_legacy(pkgid_.c_str(),
221 LOG(ERROR) << "Installation type (" << GetRequestTypeString(type_) << ")"
222 << " is not supported by external installation";
227 g_list_free_full(glist, &ClearApp2ExtDirDetail);
231 std::unique_ptr<ExternalStorage> ExternalStorage::MoveInstalledStorage(
232 RequestType type, const boost::filesystem::path& application_root,
233 const std::string& pkgid, const std::string& package_type,
234 uid_t uid, bool is_external_move) {
236 std::unique_ptr<ExternalStorage> external_storage(
237 new ExternalStorage(type, pkgid, package_type, application_root, uid,
239 if (!external_storage->Initialize(application_root)) {
240 LOG(WARNING) << "Cannot initialize external storage for move";
244 return external_storage;
247 std::unique_ptr<ExternalStorage> ExternalStorage::AcquireExternalStorage(
248 RequestType type, const boost::filesystem::path& application_root,
249 const std::string& pkgid, const std::string& package_type,
250 const boost::filesystem::path& space_requirement,
252 std::unique_ptr<ExternalStorage> external_storage(
253 new ExternalStorage(type, pkgid, package_type, application_root, uid));
254 if (!external_storage->Initialize(space_requirement)) {
255 LOG(WARNING) << "Cannot initialize external storage for request";
258 return external_storage;
261 std::unique_ptr<ExternalStorage> ExternalStorage::MigrateExternalStorage(
262 RequestType type, const std::string& pkgid, uid_t uid) {
263 std::unique_ptr<ExternalStorage> external_storage(
264 new ExternalStorage(type, pkgid, uid));
265 bf::path empty_path("");
266 if (!external_storage->Initialize(empty_path)) {
267 LOG(WARNING) << "Cannot initialize external storage for request";
270 return external_storage;
273 } // namespace common_installer