2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <sys/socket.h>
22 #include <sys/types.h>
28 #include "pkgmgr_installer.h"
29 #include "pkgmgr_installer_debug.h"
30 #include "pkgmgr_installer_type.h"
34 constexpr int OPTVAL_PRELOAD = 1000;
35 constexpr int OPTVAL_FORCE_REMOVAL = 1001;
36 constexpr int OPTVAL_PRELOAD_RW = 1002;
37 constexpr int OPTVAL_NO_REMOVAL = 1003;
38 constexpr int OPTVAL_KEEP_RWDATA = 1004;
39 constexpr int OPTVAL_PARTIAL_RW = 1005;
40 constexpr int OPTVAL_MIGRATE_EXTIMG = 1006;
41 constexpr int OPTVAL_SKIP_CHECK_REFERENCE = 1007;
42 constexpr int OPTVAL_RECOVER_DB = 1008;
43 constexpr int OPTVAL_RECOVERY_CLEANUP = 1009;
45 constexpr const char short_opts[] = "k:l:i:d:c:m:t:o:r:p:s:b:e:M:y:u:w:D:A:qGS";
46 constexpr const struct option long_opts[] = {
47 { "session-id", 1, nullptr, 'k' },
48 { "license-path", 1, nullptr, 'l' },
49 { "install", 1, nullptr, 'i' },
50 { "uninstall", 1, nullptr, 'd' },
51 { "clear", 1, nullptr, 'c' },
52 { "move", 1, nullptr, 'm' },
53 { "move-type", 1, nullptr, 't' },
54 { "optional-data", 0, nullptr, 'o' },
55 { "reinstall", 0, nullptr, 'r' },
56 { "caller-pkgid", 1, nullptr, 'p' },
57 { "tep-path", 1, nullptr, 'e' },
58 { "tep-move", 1, nullptr, 'M' },
59 { "smack", 1, nullptr, 's' },
60 { "manifest-direct-install", 1, nullptr, 'y' },
61 { "mount-install", 1, nullptr, 'w' },
62 { "recovery", 1, nullptr, 'b' },
63 { "debug-mode", 0, nullptr, 'G' },
64 { "skip-optimization", 0, nullptr, 'S' },
65 { "preload", 0, nullptr, OPTVAL_PRELOAD },
66 { "force-remove", 0, nullptr, OPTVAL_FORCE_REMOVAL },
67 { "preload-rw", 0, nullptr, OPTVAL_PRELOAD_RW },
68 { "no-remove", 0, nullptr, OPTVAL_NO_REMOVAL },
69 { "keep-rwdata", 0, nullptr, OPTVAL_KEEP_RWDATA },
70 { "partial-rw", 0, nullptr, OPTVAL_PARTIAL_RW },
71 { "migrate-extimg", 1, nullptr, OPTVAL_MIGRATE_EXTIMG },
72 { "skip-check-reference", 0, nullptr, OPTVAL_SKIP_CHECK_REFERENCE },
73 { "recover-db", 1, nullptr, OPTVAL_RECOVER_DB },
74 { "recovery-cleanup", 0, nullptr, OPTVAL_RECOVERY_CLEANUP },
78 static const char* __get_signal_name(
79 const std::unique_ptr<pkgmgr::installer::Request>& req,
80 const char* key, const char* pkg_type) {
81 if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0)
83 else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
85 else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
86 return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
87 else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0)
89 else if (req->IsUpgrade())
90 return PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
93 switch (req->GetRequestType()) {
94 case PKGMGR_REQ_INSTALL:
95 case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
96 case PKGMGR_REQ_MOUNT_INSTALL:
97 case PKGMGR_REQ_REINSTALL:
98 case PKGMGR_REQ_ENABLE_PKG:
99 case PKGMGR_REQ_RECOVER:
100 return PKGMGR_INSTALLER_INSTALL_EVENT_STR;
101 case PKGMGR_REQ_UNINSTALL:
102 case PKGMGR_REQ_DISABLE_PKG:
103 return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
104 case PKGMGR_REQ_UPGRADE:
105 return PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
106 case PKGMGR_REQ_MOVE:
107 return PKGMGR_INSTALLER_MOVE_EVENT_STR;
108 case PKGMGR_REQ_ENABLE_APP:
109 return PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR;
110 case PKGMGR_REQ_DISABLE_APP:
111 return PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR;
112 case PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN:
113 return PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR;
114 case PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN:
115 return PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
116 case PKGMGR_REQ_CLEAR:
117 return PKGMGR_INSTALLER_CLEAR_EVENT_STR;
118 case PKGMGR_REQ_GETSIZE:
119 return PKGMGR_INSTALLER_GET_SIZE_KEY_STR;
120 case PKGMGR_REQ_RES_COPY:
121 return PKGMGR_INSTALLER_RES_COPY_EVENT_STR;
122 case PKGMGR_REQ_RES_CREATE_DIR:
123 return PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR;
124 case PKGMGR_REQ_RES_REMOVE:
125 return PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR;
126 case PKGMGR_REQ_RES_UNINSTALL:
127 return PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR;
130 _E("cannot find type");
138 namespace installer {
140 Control::Control(bool offline) {
142 signal_.reset(new pkg_group::PkgSignal("", true));
145 request_ = std::make_unique<Request>();
147 option_map_[OPTVAL_PRELOAD] = [](const std::unique_ptr<Request>& req) {
148 req->is_preload_ = true;
149 _D("preload request [%d]", req->is_preload_);
153 option_map_[OPTVAL_FORCE_REMOVAL] = [](const std::unique_ptr<Request>& req) {
154 req->force_removal_ = true;
155 _D("force-remove request [%d]", req->force_removal_);
159 option_map_[OPTVAL_PRELOAD_RW] = [](const std::unique_ptr<Request>& req) {
160 req->is_preload_rw_ = true;
161 _D("preload-rw request [%d]", req->is_preload_rw_);
165 option_map_[OPTVAL_NO_REMOVAL] = [](const std::unique_ptr<Request>& req) {
166 req->no_removal_ = true;
167 _D("no-remove request [%d]", req->no_removal_);
171 option_map_[OPTVAL_KEEP_RWDATA] = [](const std::unique_ptr<Request>& req) {
172 req->keep_rwdata_ = true;
173 _D("keep-rwdata request [%d]", req->keep_rwdata_);
177 option_map_[OPTVAL_PARTIAL_RW] = [](const std::unique_ptr<Request>& req) {
178 req->partial_rw_ = true;
179 _D("partial-rw request [%d]", req->partial_rw_);
183 option_map_[OPTVAL_MIGRATE_EXTIMG] = [this](const std::unique_ptr<Request>& req) {
186 mode_ = OPTVAL_MIGRATE_EXTIMG;
187 req->request_type_ = PKGMGR_REQ_MIGRATE_EXTIMG;
188 req->pkgmgr_info_ = optarg;
189 ParseMultiplePkgs(req);
190 _D("legacy extimg migration requested");
194 option_map_[OPTVAL_SKIP_CHECK_REFERENCE] = [](const std::unique_ptr<Request>& req) {
195 req->skip_check_reference_ = true;
199 option_map_[OPTVAL_RECOVER_DB] = [this](const std::unique_ptr<Request>& req) {
200 req->request_type_ = PKGMGR_REQ_RECOVER_DB;
201 req->pkgmgr_info_ = optarg;
202 ParseMultiplePkgs(req);
206 option_map_[OPTVAL_RECOVERY_CLEANUP] = [](const std::unique_ptr<Request>& req) {
207 req->recovery_cleanup_ = true;
211 option_map_['k'] = [](const std::unique_ptr<Request>& req) {
212 req->session_id_ = optarg;
216 option_map_['l'] = [](const std::unique_ptr<Request>& req) {
217 req->license_path_ = optarg;
221 option_map_['i'] = [this](const std::unique_ptr<Request>& req) {
225 req->request_type_ = PKGMGR_REQ_INSTALL;
226 req->pkgmgr_info_ = optarg;
227 ParseMultiplePkgs(req);
228 _D("option is [i] pkgid[%s]", req->pkgmgr_info_.c_str());
232 option_map_['e'] = [](const std::unique_ptr<Request>& req) {
233 req->tep_path_ = optarg;
234 _D("option is [e] tep_path[%s]", req->tep_path_.c_str());
238 option_map_['M'] = [](const std::unique_ptr<Request>& req) {
239 if (strcmp(optarg, "tep_move") == 0)
240 req->tep_move_ = true;
242 req->tep_move_ = false;
243 _D("option is [M] tep_move[%d]", req->tep_move_);
247 option_map_['d'] = [this](const std::unique_ptr<Request>& req) {
251 req->request_type_ = PKGMGR_REQ_UNINSTALL;
252 req->pkgmgr_info_ = optarg;
253 ParseMultiplePkgs(req);
257 option_map_['c'] = [this](const std::unique_ptr<Request>& req) {
261 req->request_type_ = PKGMGR_REQ_CLEAR;
262 req->pkgmgr_info_ = optarg;
263 ParseMultiplePkgs(req);
267 option_map_['m'] = [this](const std::unique_ptr<Request>& req) {
271 req->request_type_ = PKGMGR_REQ_MOVE;
272 req->pkgmgr_info_ = optarg;
273 ParseMultiplePkgs(req);
277 option_map_['r'] = [this](const std::unique_ptr<Request>& req) {
281 req->request_type_ = PKGMGR_REQ_REINSTALL;
282 req->pkgmgr_info_ = optarg;
283 ParseMultiplePkgs(req);
287 option_map_['t'] = [](const std::unique_ptr<Request>& req) {
288 req->move_type_ = atoi(optarg);
292 option_map_['p'] = [](const std::unique_ptr<Request>& req) {
293 req->caller_pkgid_ = optarg;
297 option_map_['s'] = [this](const std::unique_ptr<Request>& req) {
301 req->request_type_ = PKGMGR_REQ_SMACK;
302 req->pkgmgr_info_ = optarg;
303 ParseMultiplePkgs(req);
307 option_map_['o'] = [](const std::unique_ptr<Request>& req) {
308 req->optional_data_ = optarg;
312 option_map_['y'] = [this](const std::unique_ptr<Request>& req) {
313 req->request_type_ = PKGMGR_REQ_MANIFEST_DIRECT_INSTALL;
314 req->pkgmgr_info_ = optarg;
315 ParseMultiplePkgs(req);
319 option_map_['w'] = [this](const std::unique_ptr<Request>& req) {
320 req->request_type_ = PKGMGR_REQ_MOUNT_INSTALL;
321 req->pkgmgr_info_ = optarg;
322 ParseMultiplePkgs(req);
326 option_map_['b'] = [this](const std::unique_ptr<Request>& req) {
330 req->request_type_ = PKGMGR_REQ_RECOVER;
331 req->pkgmgr_info_ = optarg;
332 ParseMultiplePkgs(req);
336 option_map_['D'] = [this](const std::unique_ptr<Request>& req) {
337 req->request_type_ = PKGMGR_REQ_DISABLE_PKG;
338 req->pkgmgr_info_ = optarg;
339 ParseMultiplePkgs(req);
343 option_map_['A'] = [this](const std::unique_ptr<Request>& req) {
344 req->request_type_ = PKGMGR_REQ_ENABLE_PKG;
345 req->pkgmgr_info_ = optarg;
346 ParseMultiplePkgs(req);
350 option_map_['u'] = [](const std::unique_ptr<Request>& req) {
351 req->target_uid_ = (uid_t)atoi(optarg);
355 option_map_['G'] = [](const std::unique_ptr<Request>& req) {
356 req->debug_mode_ = true;
360 option_map_['S'] = [](const std::unique_ptr<Request>& req) {
361 req->skip_optimization_ = true;
366 Control::~Control() = default;
368 void Control::ParseMultiplePkgs(const std::unique_ptr<Request>& req) {
369 while ((optind <= argc_) && (*argv_[optind - 1] != '-')) {
370 req->pkgs_.push_back(argv_[optind - 1]);
376 const std::unique_ptr<Request>& Control::GetRequest() const {
380 int Control::SendSignal(std::string pkg_type, std::string pkgid,
381 std::string appid, std::string key, std::string val) {
386 auto& req = GetRequest();
387 std::vector<rpc_port::PkgSignal::PkgInfo> pkgs;
388 pkgs.emplace_back(std::move(pkgid), std::move(appid), std::move(pkg_type));
389 signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), std::move(pkgs),
394 int Control::SendSignals(std::string key, std::string val) {
399 auto& req = GetRequest();
400 signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), pkgs_, key, val);
404 int Control::SendSignalForResource(std::string pkgid, std::string status,
405 rpc_port::PkgSignal::ExtraData* event_info) {
411 auto& req = GetRequest();
412 const char* signal_name = __get_signal_name(req, "", "");
414 _E("unknown signal type");
418 signal_->AsyncResultForResource(signal_name, req->GetUid(),
419 req->GetSessionId(), std::move(pkgid), std::move(status), *event_info);
423 static int __send_signal_to_agent(uid_t uid, void* data, size_t len) {
425 struct sockaddr_un sa;
428 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
430 _E("failed to create socket: %d", errno);
434 sa.sun_family = AF_UNIX;
435 snprintf(sa.sun_path, sizeof(sa.sun_path), "/run/pkgmgr/agent/%d", uid);
437 r = connect(fd, (struct sockaddr*)&sa, sizeof(sa));
439 _E("failed to connect socket(%s): %d", sa.sun_path, errno);
444 r = send(fd, data, len, MSG_NOSIGNAL);
446 _E("failed to send data: %d", errno);
456 int Control::SendSignalForUid(uid_t uid, std::string pkg_type,
457 std::string pkgid, std::string appid, std::string key, std::string val) {
463 const auto& req = GetRequest();
464 const char* sid = req->GetSessionId().c_str();
466 const char* signal_name;
468 GVariantBuilder* builder;
476 data_len = sizeof(size_t) + sizeof(gsize);
478 signal_name = __get_signal_name(req, key.c_str(), pkg_type.c_str());
480 _E("unknown signal name");
484 /* including null byte */
485 name_size = strlen(signal_name) + 1;
486 data_len += name_size;
488 builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
489 g_variant_builder_add(builder, "(sss)", pkgid.c_str(),
490 appid.c_str(), pkg_type.c_str());
491 gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid,
492 builder, key.c_str(), val.c_str());
493 g_variant_builder_unref(builder);
495 _E("failed to create GVariant instance");
498 gv_len = g_variant_get_size(gv);
499 gv_data = g_malloc(gv_len);
500 g_variant_store(gv, gv_data);
504 data = malloc(data_len);
511 memcpy(ptr, &name_size, sizeof(size_t));
512 ptr += sizeof(size_t);
513 memcpy(ptr, &gv_len, sizeof(gsize));
514 ptr += sizeof(gsize);
515 memcpy(ptr, signal_name, name_size);
517 memcpy(ptr, gv_data, gv_len);
520 if (__send_signal_to_agent(uid, data, data_len)) {
521 _E("failed to send signal to agent");
531 int Control::SendSignalsForUid(uid_t uid, std::string key, std::string val) {
537 const auto& req = GetRequest();
538 const char* sid = req->GetSessionId().c_str();
540 const char* signal_name;
542 GVariantBuilder* builder;
550 data_len = sizeof(size_t) + sizeof(gsize);
552 signal_name = __get_signal_name(req, key.c_str(), "");
554 _E("unknown signal name");
558 /* including null byte */
559 name_size = strlen(signal_name) + 1;
560 data_len += name_size;
562 builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
563 for (const auto& pkg : pkgs_)
564 g_variant_builder_add(builder, "(sss)", pkg.GetPkgid().c_str(),
565 pkg.GetAppid().c_str(), pkg.GetPkgType().c_str());
566 gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid,
567 builder, key.c_str(), val.c_str());
568 g_variant_builder_unref(builder);
570 _E("failed to create GVariant instance");
573 gv_len = g_variant_get_size(gv);
574 gv_data = g_malloc(gv_len);
575 g_variant_store(gv, gv_data);
579 data = malloc(data_len);
586 memcpy(ptr, &name_size, sizeof(size_t));
587 ptr += sizeof(size_t);
588 memcpy(ptr, &gv_len, sizeof(gsize));
589 ptr += sizeof(gsize);
590 memcpy(ptr, signal_name, name_size);
592 memcpy(ptr, gv_data, gv_len);
595 if (__send_signal_to_agent(uid, data, data_len)) {
596 _E("failed to send signal to agent");
606 static GVariant* __get_gvariant_from_event_info(
607 pkgmgr_res_event_info* event_info) {
608 rpc_port::PkgSignal::ExtraData* info =
609 reinterpret_cast<rpc_port::PkgSignal::ExtraData*>(event_info);
610 GVariantBuilder* builder;
613 res_event_path_state_t* path_state;
615 builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
616 if (builder == NULL) {
621 for (const auto& p : info->GetPaths())
622 g_variant_builder_add(builder, "(si)", p.GetPath(), p.GetState());
624 result = g_variant_new("(ia(si))", info->GetErrCode(), builder);
625 g_variant_builder_unref(builder);
627 if (result == NULL) {
628 _E("Fail to create extra data");
635 int Control::SendSignalForResourceForUid(uid_t uid, std::string pkgid,
636 std::string status, rpc_port::PkgSignal::ExtraData* event_info) {
642 const auto& req = GetRequest();
643 const char* sid = req->GetSessionId().c_str();
645 const char* signal_name;
653 GVariant* extra_param;
655 data_len = sizeof(size_t) + sizeof(gsize);
657 signal_name = __get_signal_name(req, "", "");
659 _E("unknown signal name");
663 /* including null byte */
664 name_size = strlen(signal_name) + 1;
665 data_len += name_size;
667 extra_param = __get_gvariant_from_event_info(event_info);
668 if (extra_param == NULL) {
669 _E("Fail to get extra parameter");
673 gv = g_variant_new("(usssv)", req->GetUid(), sid,
674 pkgid.c_str(), status.c_str(), extra_param);
676 _E("failed to create GVariant instance");
680 gv_len = g_variant_get_size(gv);
681 gv_data = g_malloc(gv_len);
682 g_variant_store(gv, gv_data);
686 data = malloc(data_len);
693 memcpy(ptr, &name_size, sizeof(size_t));
694 ptr += sizeof(size_t);
695 memcpy(ptr, &gv_len, sizeof(gsize));
696 ptr += sizeof(gsize);
697 memcpy(ptr, signal_name, name_size);
699 memcpy(ptr, gv_data, gv_len);
702 if (__send_signal_to_agent(uid, data, data_len)) {
703 _E("failed to send signal to agent");
713 void Control::AddPkg(std::string pkgid, std::string pkg_type) {
714 pkgs_.emplace_back(rpc_port::PkgSignal::PkgInfo(std::move(pkgid),
715 "", std::move(pkg_type)));
718 int Control::SetRequestFromArgv(const int argc, char** argv) {
726 int c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx);
730 if (option_map_.find(c) != option_map_.end()) {
731 int ret = option_map_[c](request_);
740 } // namespace installer
741 } // namespace pkgmgr