1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "bundle_command.h"
16
17 #include <chrono>
18 #include <cstdlib>
19 #include <cstring>
20 #include <future>
21 #include <getopt.h>
22 #include <unistd.h>
23 #include <vector>
24
25 #include "app_log_wrapper.h"
26 #include "appexecfwk_errors.h"
27 #include "bundle_command_common.h"
28 #include "bundle_death_recipient.h"
29 #include "bundle_mgr_client.h"
30 #include "bundle_mgr_proxy.h"
31 #include "clean_cache_callback_host.h"
32 #include "parameter.h"
33 #include "quick_fix_command.h"
34 #include "status_receiver_impl.h"
35 #include "string_ex.h"
36
37 namespace OHOS {
38 namespace AppExecFwk {
39 namespace {
40 const std::string BUNDLE_NAME_EMPTY = "";
41 const int32_t INDEX_OFFSET = 2;
42 const int32_t MAX_WAITING_TIME = 3000;
43 const int32_t DEVICE_UDID_LENGTH = 65;
44 const int32_t MAX_ARGUEMENTS_NUMBER = 3;
45 const int32_t MINIMUM_WAITTING_TIME = 180; // 3 mins
46 const int32_t MAXIMUM_WAITTING_TIME = 600; // 10 mins
47
48 const std::string SHORT_OPTIONS = "hp:rn:m:a:cdu:w:";
49 const struct option LONG_OPTIONS[] = {
50 {"help", no_argument, nullptr, 'h'},
51 {"bundle-path", required_argument, nullptr, 'p'},
52 {"replace", no_argument, nullptr, 'r'},
53 {"bundle-name", required_argument, nullptr, 'n'},
54 {"module-name", required_argument, nullptr, 'm'},
55 {"ability-name", required_argument, nullptr, 'a'},
56 {"bundle-info", no_argument, nullptr, 'i'},
57 {"cache", no_argument, nullptr, 'c'},
58 {"data", no_argument, nullptr, 'd'},
59 {"is-removable", required_argument, nullptr, 'i'},
60 {"user-id", required_argument, nullptr, 'u'},
61 {"waitting-time", required_argument, nullptr, 'w'},
62 {"keep-data", no_argument, nullptr, 'k'},
63 {nullptr, 0, nullptr, 0},
64 };
65
66 const std::string SHORT_OPTIONS_DUMP = "hn:aisu:d:";
67 const struct option LONG_OPTIONS_DUMP[] = {
68 {"help", no_argument, nullptr, 'h'},
69 {"bundle-name", required_argument, nullptr, 'n'},
70 {"all", no_argument, nullptr, 'a'},
71 {"bundle-info", no_argument, nullptr, 'i'},
72 {"shortcut-info", no_argument, nullptr, 's'},
73 {"user-id", required_argument, nullptr, 'u'},
74 {"device-id", required_argument, nullptr, 'd'},
75 {nullptr, 0, nullptr, 0},
76 };
77
78 const std::string SHORT_OPTIONS_GET = "hu";
79 const struct option LONG_OPTIONS_GET[] = {
80 {"help", no_argument, nullptr, 'h'},
81 {"udid", no_argument, nullptr, 'u'},
82 {nullptr, 0, nullptr, 0},
83 };
84 const std::string SHORT_OPTIONS_DUMP_DEPENDENCIES = "hn:m:";
85 const struct option LONG_OPTIONS_DUMP_DEPENDENCIES[] = {
86 {"help", no_argument, nullptr, 'h'},
87 {"bundle-name", required_argument, nullptr, 'n'},
88 {"module-name", required_argument, nullptr, 'm'},
89 {nullptr, 0, nullptr, 0},
90 };
91 } // namespace
92
93 class CleanCacheCallbackImpl : public CleanCacheCallbackHost {
94 public:
CleanCacheCallbackImpl()95 CleanCacheCallbackImpl() : signal_(std::make_shared<std::promise<bool>>())
96 {}
~CleanCacheCallbackImpl()97 virtual ~CleanCacheCallbackImpl() override
98 {}
99 virtual void OnCleanCacheFinished(bool error) override;
100 bool GetResultCode();
101 private:
102 std::shared_ptr<std::promise<bool>> signal_;
103 DISALLOW_COPY_AND_MOVE(CleanCacheCallbackImpl);
104 };
105
OnCleanCacheFinished(bool error)106 void CleanCacheCallbackImpl::OnCleanCacheFinished(bool error)
107 {
108 if (signal_ != nullptr) {
109 signal_->set_value(error);
110 }
111 }
112
GetResultCode()113 bool CleanCacheCallbackImpl::GetResultCode()
114 {
115 if (signal_ != nullptr) {
116 auto future = signal_->get_future();
117 std::chrono::milliseconds span(MAX_WAITING_TIME);
118 if (future.wait_for(span) == std::future_status::timeout) {
119 return false;
120 }
121 return future.get();
122 }
123 return false;
124 }
125
BundleManagerShellCommand(int argc,char * argv[])126 BundleManagerShellCommand::BundleManagerShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, TOOL_NAME)
127 {}
128
CreateCommandMap()129 ErrCode BundleManagerShellCommand::CreateCommandMap()
130 {
131 commandMap_ = {
132 {"help", std::bind(&BundleManagerShellCommand::RunAsHelpCommand, this)},
133 {"install", std::bind(&BundleManagerShellCommand::RunAsInstallCommand, this)},
134 {"uninstall", std::bind(&BundleManagerShellCommand::RunAsUninstallCommand, this)},
135 {"dump", std::bind(&BundleManagerShellCommand::RunAsDumpCommand, this)},
136 {"dump-dependencies", std::bind(&BundleManagerShellCommand::RunAsDumpDependenciesCommand, this)},
137 {"clean", std::bind(&BundleManagerShellCommand::RunAsCleanCommand, this)},
138 {"enable", std::bind(&BundleManagerShellCommand::RunAsEnableCommand, this)},
139 {"disable", std::bind(&BundleManagerShellCommand::RunAsDisableCommand, this)},
140 {"get", std::bind(&BundleManagerShellCommand::RunAsGetCommand, this)},
141 {"quickfix", std::bind(&BundleManagerShellCommand::RunAsQuickFixCommand, this)},
142 };
143
144 return OHOS::ERR_OK;
145 }
146
CreateMessageMap()147 ErrCode BundleManagerShellCommand::CreateMessageMap()
148 {
149 messageMap_ = BundleCommandCommon::bundleMessageMap_;
150 return OHOS::ERR_OK;
151 }
152
Init()153 ErrCode BundleManagerShellCommand::Init()
154 {
155 ErrCode result = OHOS::ERR_OK;
156
157 if (bundleMgrProxy_ == nullptr) {
158 bundleMgrProxy_ = BundleCommandCommon::GetBundleMgrProxy();
159 if (bundleMgrProxy_) {
160 if (bundleInstallerProxy_ == nullptr) {
161 bundleInstallerProxy_ = bundleMgrProxy_->GetBundleInstaller();
162 }
163 }
164 }
165
166 if ((bundleMgrProxy_ == nullptr) || (bundleInstallerProxy_ == nullptr) ||
167 (bundleInstallerProxy_->AsObject() == nullptr)) {
168 result = OHOS::ERR_INVALID_VALUE;
169 }
170
171 return result;
172 }
173
RunAsHelpCommand()174 ErrCode BundleManagerShellCommand::RunAsHelpCommand()
175 {
176 resultReceiver_.append(HELP_MSG);
177
178 return OHOS::ERR_OK;
179 }
180
RunAsInstallCommand()181 ErrCode BundleManagerShellCommand::RunAsInstallCommand()
182 {
183 int result = OHOS::ERR_OK;
184 InstallFlag installFlag = InstallFlag::REPLACE_EXISTING;
185 int counter = 0;
186 std::vector<std::string> bundlePath;
187 int index = 0;
188 int32_t userId = Constants::ALL_USERID;
189 int32_t waittingTime = MINIMUM_WAITTING_TIME;
190 while (true) {
191 counter++;
192 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
193 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
194 if (optind < 0 || optind > argc_) {
195 return OHOS::ERR_INVALID_VALUE;
196 }
197 if (option == -1) {
198 if (counter == 1) {
199 // When scanning the first argument
200 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
201 // 'bm install' with no option: bm install
202 // 'bm install' with a wrong argument: bm install xxx
203 APP_LOGD("'bm install' with no option.");
204 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
205 result = OHOS::ERR_INVALID_VALUE;
206 }
207 }
208 break;
209 }
210
211 if (option == '?') {
212 switch (optopt) {
213 case 'p': {
214 // 'bm install -p' with no argument: bm install -p
215 // 'bm install --bundle-path' with no argument: bm install --bundle-path
216 APP_LOGD("'bm install' with no argument.");
217 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
218 result = OHOS::ERR_INVALID_VALUE;
219 break;
220 }
221 case 'u': {
222 // 'bm install -u' with no argument: bm install -u
223 // 'bm install --user-id' with no argument: bm install --user-id
224 APP_LOGD("'bm install -u' with no argument.");
225 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
226 result = OHOS::ERR_INVALID_VALUE;
227 break;
228 }
229 case 'w': {
230 // 'bm install -w' with no argument: bm install -w
231 // 'bm install --waitting-time' with no argument: bm install --waitting-time
232 APP_LOGD("'bm install -w' with no argument.");
233 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
234 result = OHOS::ERR_INVALID_VALUE;
235 break;
236 }
237 default: {
238 // 'bm install' with an unknown option: bm install -x
239 // 'bm install' with an unknown option: bm install -xxx
240 std::string unknownOption = "";
241 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
242 APP_LOGD("'bm install' with an unknown option.");
243 resultReceiver_.append(unknownOptionMsg);
244 result = OHOS::ERR_INVALID_VALUE;
245 break;
246 }
247 }
248 break;
249 }
250
251 switch (option) {
252 case 'h': {
253 // 'bm install -h'
254 // 'bm install --help'
255 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
256 result = OHOS::ERR_INVALID_VALUE;
257 break;
258 }
259 case 'p': {
260 // 'bm install -p <bundle-file-path>'
261 // 'bm install --bundle-path <bundle-file-path>'
262 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
263 if (GetBundlePath(optarg, bundlePath) != OHOS::ERR_OK) {
264 APP_LOGD("'bm install' with no argument.");
265 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
266
267 return OHOS::ERR_INVALID_VALUE;
268 }
269 index = optind;
270 break;
271 }
272 case 'r': {
273 // 'bm install -r'
274 // 'bm install --replace'
275 installFlag = InstallFlag::REPLACE_EXISTING;
276 break;
277 }
278 case 'u': {
279 // 'bm install -p <bundle-file-path> -u userId'
280 // 'bm install --bundle-path <bundle-file-path> --user-id userId'
281 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
282 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
283 APP_LOGE("bm install with error userId %{private}s", optarg);
284 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
285 return OHOS::ERR_INVALID_VALUE;
286 }
287 break;
288 }
289 case 'w': {
290 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
291 if (!OHOS::StrToInt(optarg, waittingTime) || waittingTime < MINIMUM_WAITTING_TIME ||
292 waittingTime > MAXIMUM_WAITTING_TIME) {
293 APP_LOGE("bm install with error waittingTime %{private}s", optarg);
294 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
295 return OHOS::ERR_INVALID_VALUE;
296 }
297 break;
298 }
299 default: {
300 result = OHOS::ERR_INVALID_VALUE;
301 break;
302 }
303 }
304 }
305
306 for (; index < argc_ && index >= INDEX_OFFSET; ++index) {
307 if (argList_[index - INDEX_OFFSET] == "-r" || argList_[index - INDEX_OFFSET] == "--replace" ||
308 argList_[index - INDEX_OFFSET] == "-p" || argList_[index - INDEX_OFFSET] == "--bundle-path" ||
309 argList_[index - INDEX_OFFSET] == "-u" || argList_[index - INDEX_OFFSET] == "--user-id" ||
310 argList_[index - INDEX_OFFSET] == "-w" || argList_[index - INDEX_OFFSET] == "--waitting-time") {
311 break;
312 }
313 if (GetBundlePath(argList_[index - INDEX_OFFSET], bundlePath) != OHOS::ERR_OK) {
314 bundlePath.clear();
315 APP_LOGD("'bm install' with error arguments.");
316 resultReceiver_.append("error value for the chosen option");
317 result = OHOS::ERR_INVALID_VALUE;
318 }
319 }
320
321 for (auto &path : bundlePath) {
322 APP_LOGD("install hap path %{private}s", path.c_str());
323 }
324
325 if (result == OHOS::ERR_OK) {
326 if (resultReceiver_ == "" && bundlePath.empty()) {
327 // 'bm install ...' with no bundle path option
328 APP_LOGD("'bm install' with no bundle path option.");
329 resultReceiver_.append(HELP_MSG_NO_BUNDLE_PATH_OPTION + "\n");
330 result = OHOS::ERR_INVALID_VALUE;
331 }
332 }
333
334 if (result != OHOS::ERR_OK) {
335 resultReceiver_.append(HELP_MSG_INSTALL);
336 } else {
337 InstallParam installParam;
338 installParam.installFlag = installFlag;
339 installParam.userId = userId;
340 int32_t installResult = InstallOperation(bundlePath, installParam, waittingTime);
341 if (installResult == OHOS::ERR_OK) {
342 resultReceiver_ = STRING_INSTALL_BUNDLE_OK + "\n";
343 } else {
344 resultReceiver_ = STRING_INSTALL_BUNDLE_NG + "\n";
345 resultReceiver_.append(GetMessageFromCode(installResult));
346 }
347 }
348
349 return result;
350 }
351
GetBundlePath(const std::string & param,std::vector<std::string> & bundlePaths) const352 ErrCode BundleManagerShellCommand::GetBundlePath(const std::string& param,
353 std::vector<std::string>& bundlePaths) const
354 {
355 if (param.empty()) {
356 return OHOS::ERR_INVALID_VALUE;
357 }
358 if (param == "-r" || param == "--replace" || param == "-p" ||
359 param == "--bundle-path" || param == "-u" || param == "--user-id" ||
360 param == "-w" || param == "--waitting-time") {
361 return OHOS::ERR_INVALID_VALUE;
362 }
363 bundlePaths.emplace_back(param);
364 return OHOS::ERR_OK;
365 }
366
RunAsUninstallCommand()367 ErrCode BundleManagerShellCommand::RunAsUninstallCommand()
368 {
369 int result = OHOS::ERR_OK;
370 int counter = 0;
371 std::string bundleName = "";
372 std::string moduleName = "";
373 int32_t userId = Constants::ALL_USERID;
374 bool isKeepData = false;
375 while (true) {
376 counter++;
377 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
378 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
379 if (optind < 0 || optind > argc_) {
380 return OHOS::ERR_INVALID_VALUE;
381 }
382 if (option == -1) {
383 if (counter == 1) {
384 // When scanning the first argument
385 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
386 // 'bm uninstall' with no option: bm uninstall
387 // 'bm uninstall' with a wrong argument: bm uninstall xxx
388 APP_LOGD("'bm uninstall' %{public}s", HELP_MSG_NO_OPTION.c_str());
389 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
390 result = OHOS::ERR_INVALID_VALUE;
391 }
392 }
393 break;
394 }
395
396 if (option == '?') {
397 switch (optopt) {
398 case 'n': {
399 // 'bm uninstall -n' with no argument: bm uninstall -n
400 // 'bm uninstall --bundle-name' with no argument: bm uninstall --bundle-name
401 APP_LOGD("'bm uninstall -n' with no argument.");
402 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
403 result = OHOS::ERR_INVALID_VALUE;
404 break;
405 }
406 case 'm': {
407 // 'bm uninstall -m' with no argument: bm uninstall -m
408 // 'bm uninstall --module-name' with no argument: bm uninstall --module-name
409 APP_LOGD("'bm uninstall -m' with no argument.");
410 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
411 result = OHOS::ERR_INVALID_VALUE;
412 break;
413 }
414 case 'u': {
415 // 'bm uninstall -n <bundleName> -u userId'
416 // 'bm uninstall --bundle-name <bundleName> --user-id userId'
417 APP_LOGD("'bm uninstall -u' with no argument.");
418 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
419 result = OHOS::ERR_INVALID_VALUE;
420 break;
421 }
422 case 'k': {
423 // 'bm uninstall -n <bundleName> -k'
424 // 'bm uninstall --bundle-name <bundleName> --keep-data'
425 APP_LOGD("'bm uninstall -k'");
426 isKeepData = true;
427 break;
428 }
429 default: {
430 // 'bm uninstall' with an unknown option: bm uninstall -x
431 // 'bm uninstall' with an unknown option: bm uninstall -xxx
432 std::string unknownOption = "";
433 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
434 APP_LOGD("'bm uninstall' with an unknown option.");
435 resultReceiver_.append(unknownOptionMsg);
436 result = OHOS::ERR_INVALID_VALUE;
437 break;
438 }
439 }
440 break;
441 }
442
443 switch (option) {
444 case 'h': {
445 // 'bm uninstall -h'
446 // 'bm uninstall --help'
447 APP_LOGD("'bm uninstall %{public}s'", argv_[optind - 1]);
448 result = OHOS::ERR_INVALID_VALUE;
449 break;
450 }
451 case 'n': {
452 // 'bm uninstall -n xxx'
453 // 'bm uninstall --bundle-name xxx'
454 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
455 bundleName = optarg;
456 break;
457 }
458 case 'm': {
459 // 'bm uninstall -m xxx'
460 // 'bm uninstall --module-name xxx'
461 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
462 moduleName = optarg;
463 break;
464 }
465 case 'u': {
466 // 'bm uninstall -n <bundleName> -u userId'
467 // 'bm uninstall --bundle-name <bundleName> --user-id userId'
468 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
469 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
470 APP_LOGE("bm uninstall with error userId %{private}s", optarg);
471 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
472 return OHOS::ERR_INVALID_VALUE;
473 }
474 break;
475 }
476 case 'k': {
477 // 'bm uninstall -n <bundleName> -k'
478 // 'bm uninstall --bundle-name <bundleName> --keep-data'
479 APP_LOGD("'bm uninstall %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
480 isKeepData = true;
481 break;
482 }
483 default: {
484 result = OHOS::ERR_INVALID_VALUE;
485 break;
486 }
487 }
488 }
489
490 if (result == OHOS::ERR_OK) {
491 if (resultReceiver_ == "" && bundleName.size() == 0) {
492 // 'bm uninstall ...' with no bundle name option
493 APP_LOGD("'bm uninstall' with bundle name option.");
494 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
495 result = OHOS::ERR_INVALID_VALUE;
496 }
497 }
498
499 if (result != OHOS::ERR_OK) {
500 resultReceiver_.append(HELP_MSG_UNINSTALL);
501 } else {
502 InstallParam installParam;
503 installParam.userId = userId;
504 installParam.isKeepData = isKeepData;
505 int32_t uninstallResult = UninstallOperation(bundleName, moduleName, installParam);
506 if (uninstallResult == OHOS::ERR_OK) {
507 resultReceiver_ = STRING_UNINSTALL_BUNDLE_OK + "\n";
508 } else {
509 resultReceiver_ = STRING_UNINSTALL_BUNDLE_NG + "\n";
510 resultReceiver_.append(GetMessageFromCode(uninstallResult));
511 }
512 }
513
514 return result;
515 }
516
RunAsDumpCommand()517 ErrCode BundleManagerShellCommand::RunAsDumpCommand()
518 {
519 int result = OHOS::ERR_OK;
520 int counter = 0;
521 std::string bundleName = "";
522 bool bundleDumpAll = false;
523 bool bundleDumpInfo = false;
524 bool bundleDumpShortcut = false;
525 bool bundleDumpDistributedBundleInfo = false;
526 std::string deviceId = "";
527 int32_t userId = Constants::ALL_USERID;
528 while (true) {
529 counter++;
530 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP.c_str(), LONG_OPTIONS_DUMP, nullptr);
531 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
532 if (optind < 0 || optind > argc_) {
533 return OHOS::ERR_INVALID_VALUE;
534 }
535 if (option == -1) {
536 if (counter == 1) {
537 // When scanning the first argument
538 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
539 // 'bm dump' with no option: bm dump
540 // 'bm dump' with a wrong argument: bm dump xxx
541 APP_LOGD("'bm dump' %{public}s", HELP_MSG_NO_OPTION.c_str());
542 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
543 result = OHOS::ERR_INVALID_VALUE;
544 }
545 }
546 break;
547 }
548 if (option == '?') {
549 switch (optopt) {
550 case 'n': {
551 // 'bm dump -n' with no argument: bm dump -n
552 // 'bm dump --bundle-name' with no argument: bm dump --bundle-name
553 APP_LOGD("'bm dump -n' with no argument.");
554 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
555 result = OHOS::ERR_INVALID_VALUE;
556 break;
557 }
558 case 'u': {
559 // 'bm dump -u' with no argument: bm dump -u
560 // 'bm dump --user-id' with no argument: bm dump --user-id
561 APP_LOGD("'bm dump -u' with no argument.");
562 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
563 result = OHOS::ERR_INVALID_VALUE;
564 break;
565 }
566 case 'd': {
567 // 'bm dump -d' with no argument: bm dump -d
568 // 'bm dump --device-id' with no argument: bm dump --device-id
569 APP_LOGD("'bm dump -d' with no argument.");
570 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
571 result = OHOS::ERR_INVALID_VALUE;
572 break;
573 }
574 default: {
575 // 'bm dump' with an unknown option: bm dump -x
576 // 'bm dump' with an unknown option: bm dump -xxx
577 std::string unknownOption = "";
578 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
579 APP_LOGD("'bm dump' with an unknown option.");
580 resultReceiver_.append(unknownOptionMsg);
581 result = OHOS::ERR_INVALID_VALUE;
582 break;
583 }
584 }
585 break;
586 }
587 switch (option) {
588 case 'h': {
589 // 'bm dump -h'
590 // 'bm dump --help'
591 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
592 result = OHOS::ERR_INVALID_VALUE;
593 break;
594 }
595 case 'a': {
596 // 'bm dump -a'
597 // 'bm dump --all'
598 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
599 bundleDumpAll = true;
600 break;
601 }
602 case 'n': {
603 // 'bm dump -n xxx'
604 // 'bm dump --bundle-name xxx'
605 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
606 bundleName = optarg;
607 bundleDumpInfo = true;
608 break;
609 }
610 case 's': {
611 // 'bm dump -n xxx -s'
612 // 'bm dump --bundle-name xxx --shortcut-info'
613 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
614 bundleDumpShortcut = true;
615 break;
616 }
617 case 'u': {
618 // 'bm dump -n <bundleName> -u userId'
619 // 'bm dump --bundle-name <bundleName> --user-id userId'
620 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
621 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
622 APP_LOGE("bm dump with error userId %{private}s", optarg);
623 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
624 return OHOS::ERR_INVALID_VALUE;
625 }
626 break;
627 }
628 case 'd': {
629 // 'bm dump -n <bundleName> -d deviceId'
630 // 'bm dump --bundle-name <bundleName> --device-id deviceId'
631 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
632 deviceId = optarg;
633 bundleDumpDistributedBundleInfo = true;
634 break;
635 }
636 default: {
637 result = OHOS::ERR_INVALID_VALUE;
638 break;
639 }
640 }
641 }
642 if (result == OHOS::ERR_OK) {
643 if ((resultReceiver_ == "") && bundleDumpShortcut && (bundleName.size() == 0)) {
644 // 'bm dump -s ...' with no bundle name option
645 APP_LOGD("'bm dump -s' with no bundle name option.");
646 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
647 result = OHOS::ERR_INVALID_VALUE;
648 }
649 if ((resultReceiver_ == "") && bundleDumpDistributedBundleInfo && (bundleName.size() == 0)) {
650 // 'bm dump d ...' with no bundle name option
651 APP_LOGD("'bm dump -d' with no bundle name option.");
652 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
653 result = OHOS::ERR_INVALID_VALUE;
654 }
655 }
656 if (result != OHOS::ERR_OK) {
657 resultReceiver_.append(HELP_MSG_DUMP);
658 } else {
659 std::string dumpResults = "";
660 APP_LOGD("dumpResults: %{public}s", dumpResults.c_str());
661 if (bundleDumpShortcut) {
662 dumpResults = DumpShortcutInfos(bundleName, userId);
663 } else if (bundleDumpDistributedBundleInfo) {
664 dumpResults = DumpDistributedBundleInfo(deviceId, bundleName);
665 } else if (bundleDumpAll) {
666 dumpResults = DumpBundleList(userId);
667 } else if (bundleDumpInfo) {
668 dumpResults = DumpBundleInfo(bundleName, userId);
669 }
670 if (dumpResults.empty() || (dumpResults == "")) {
671 dumpResults = HELP_MSG_DUMP_FAILED + "\n";
672 }
673 resultReceiver_.append(dumpResults);
674 }
675
676 return result;
677 }
678
RunAsDumpDependenciesCommand()679 ErrCode BundleManagerShellCommand::RunAsDumpDependenciesCommand()
680 {
681 int32_t result = OHOS::ERR_OK;
682 int32_t counter = 0;
683 std::string bundleName;
684 std::string moduleName;
685 while (true) {
686 counter++;
687 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP_DEPENDENCIES.c_str(),
688 LONG_OPTIONS_DUMP_DEPENDENCIES, nullptr);
689 if (optind < 0 || optind > argc_) {
690 return OHOS::ERR_INVALID_VALUE;
691 }
692 if (option == -1) {
693 if (counter == 1) {
694 // When scanning the first argument
695 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
696 // 'bm dump-dependencies' with no option: bm dump-dependencies
697 // 'bm dump-dependencies' with a wrong argument: bm dump-dependencies xxx
698 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
699 result = OHOS::ERR_INVALID_VALUE;
700 }
701 }
702 break;
703 }
704 result = ParseDependenciesCommand(option, bundleName, moduleName);
705 if (option == '?') {
706 break;
707 }
708 }
709 if (result == OHOS::ERR_OK) {
710 if ((resultReceiver_ == "") && (bundleName.size() == 0 || moduleName.size() == 0)) {
711 // 'bm dump-dependencies -n -m ...' with no bundle name option
712 resultReceiver_.append(HELP_MSG_NO_REMOVABLE_OPTION);
713 result = OHOS::ERR_INVALID_VALUE;
714 }
715 }
716 if (result != OHOS::ERR_OK) {
717 resultReceiver_.append(HELP_MSG_DUMP_DEPENDENCIES);
718 } else {
719 std::string dumpResults = DumpDependentModuleNames(bundleName, moduleName);
720 if (dumpResults.empty() || (dumpResults == "")) {
721 dumpResults = HELP_MSG_DUMP_FAILED + "\n";
722 }
723 resultReceiver_.append(dumpResults);
724 }
725 return result;
726 }
727
ParseDependenciesCommand(int32_t option,std::string & bundleName,std::string & moduleName)728 ErrCode BundleManagerShellCommand::ParseDependenciesCommand(int32_t option, std::string &bundleName,
729 std::string &moduleName)
730 {
731 int32_t result = OHOS::ERR_OK;
732 if (option == '?') {
733 switch (optopt) {
734 case 'n': {
735 // 'bm dump-dependencies -n' with no argument: bm dump-dependencies -n
736 // 'bm dump-dependencies --bundle-name' with no argument: bm dump-dependencies --bundle-name
737 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
738 result = OHOS::ERR_INVALID_VALUE;
739 break;
740 }
741 case 'm': {
742 // 'bm dump-dependencies -m' with no argument: bm dump-dependencies -m
743 // 'bm dump-dependencies --module-name' with no argument: bm dump-dependencies --module-name
744 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
745 result = OHOS::ERR_INVALID_VALUE;
746 break;
747 }
748 default: {
749 // 'bm dump-dependencies' with an unknown option: bm dump-dependencies -x
750 // 'bm dump-dependencies' with an unknown option: bm dump-dependencies -xxx
751 std::string unknownOption = "";
752 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
753 resultReceiver_.append(unknownOptionMsg);
754 result = OHOS::ERR_INVALID_VALUE;
755 break;
756 }
757 }
758 } else {
759 switch (option) {
760 case 'h': {
761 // 'bm dump-dependencies -h'
762 // 'bm dump-dependencies --help'
763 result = OHOS::ERR_INVALID_VALUE;
764 break;
765 }
766 case 'n': {
767 // 'bm dump-dependencies -n xxx'
768 // 'bm dump-dependencies --bundle-name xxx'
769 bundleName = optarg;
770 break;
771 }
772 case 'm': {
773 // 'bm dump-dependencies -m xxx'
774 // 'bm dump-dependencies --module-name xxx'
775 moduleName = optarg;
776 break;
777 }
778 default: {
779 result = OHOS::ERR_INVALID_VALUE;
780 break;
781 }
782 }
783 }
784 return result;
785 }
786
RunAsCleanCommand()787 ErrCode BundleManagerShellCommand::RunAsCleanCommand()
788 {
789 int32_t result = OHOS::ERR_OK;
790 int32_t counter = 0;
791 int32_t userId = Constants::UNSPECIFIED_USERID;
792 bool cleanCache = false;
793 bool cleanData = false;
794 std::string bundleName = "";
795 while (true) {
796 counter++;
797 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
798 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
799 if (optind < 0 || optind > argc_) {
800 return OHOS::ERR_INVALID_VALUE;
801 }
802 if (option == -1) {
803 if (counter == 1) {
804 // When scanning the first argument
805 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
806 // 'bm clean' with no option: bm clean
807 // 'bm clean' with a wrong argument: bm clean xxx
808 APP_LOGD("'bm clean' %{public}s", HELP_MSG_NO_OPTION.c_str());
809
810 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
811 result = OHOS::ERR_INVALID_VALUE;
812 }
813 }
814 break;
815 }
816
817 if (option == '?') {
818 switch (optopt) {
819 case 'n': {
820 // 'bm clean -n' with no argument: bm clean -n
821 // 'bm clean --bundle-name' with no argument: bm clean --bundle-name
822 APP_LOGD("'bm clean -n' with no argument.");
823 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
824 result = OHOS::ERR_INVALID_VALUE;
825 break;
826 }
827 case 'u': {
828 // 'bm clean -u' with no argument: bm clean -u
829 // 'bm clean --user-id' with no argument: bm clean --user-id
830 APP_LOGD("'bm clean -u' with no argument.");
831 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
832 result = OHOS::ERR_INVALID_VALUE;
833 break;
834 }
835 default: {
836 // 'bm clean' with an unknown option: bm clear -x
837 // 'bm clean' with an unknown option: bm clear -xxx
838 std::string unknownOption = "";
839 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
840 APP_LOGD("'bm clean' with an unknown option.");
841 resultReceiver_.append(unknownOptionMsg);
842 result = OHOS::ERR_INVALID_VALUE;
843 break;
844 }
845 }
846 break;
847 }
848
849 switch (option) {
850 case 'h': {
851 // 'bm clean -h'
852 // 'bm clean --help'
853 APP_LOGD("'bm clean %{public}s'", argv_[optind - 1]);
854 result = OHOS::ERR_INVALID_VALUE;
855 break;
856 }
857 case 'n': {
858 // 'bm clean -n xxx'
859 // 'bm clean --bundle-name xxx'
860 APP_LOGD("'bm clean %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
861 bundleName = optarg;
862 break;
863 }
864 case 'c': {
865 // 'bm clean -c'
866 // 'bm clean --cache'
867 APP_LOGD("'bm clean %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
868 cleanCache = cleanData ? false : true;
869 break;
870 }
871 case 'd': {
872 // 'bm clean -d'
873 // 'bm clean --data'
874 APP_LOGD("'bm clean %{public}s '", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
875 cleanData = cleanCache ? false : true;
876 break;
877 }
878 case 'u': {
879 // 'bm clean -u userId'
880 // 'bm clean --user-id userId'
881 APP_LOGD("'bm clean %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
882 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
883 APP_LOGE("bm clean with error userId %{private}s", optarg);
884 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
885 return OHOS::ERR_INVALID_VALUE;
886 }
887 break;
888 }
889 default: {
890 result = OHOS::ERR_INVALID_VALUE;
891 break;
892 }
893 }
894 }
895
896 if (result == OHOS::ERR_OK) {
897 if (resultReceiver_ == "" && bundleName.size() == 0) {
898 // 'bm clean ...' with no bundle name option
899 APP_LOGD("'bm clean' with no bundle name option.");
900 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
901 result = OHOS::ERR_INVALID_VALUE;
902 }
903 if (!cleanCache && !cleanData) {
904 APP_LOGD("'bm clean' with no '-c' or '-d' option.");
905 resultReceiver_.append(HELP_MSG_NO_DATA_OR_CACHE_OPTION + "\n");
906 result = OHOS::ERR_INVALID_VALUE;
907 }
908 }
909
910 if (result != OHOS::ERR_OK) {
911 resultReceiver_.append(HELP_MSG_CLEAN);
912 } else {
913 // bm clean -c
914 if (cleanCache) {
915 if (CleanBundleCacheFilesOperation(bundleName, userId)) {
916 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_OK + "\n";
917 } else {
918 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_NG + "\n";
919 }
920 }
921 // bm clean -d
922 if (cleanData) {
923 if (CleanBundleDataFilesOperation(bundleName, userId)) {
924 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_OK + "\n");
925 } else {
926 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_NG + "\n");
927 }
928 }
929 }
930 return result;
931 }
932
RunAsEnableCommand()933 ErrCode BundleManagerShellCommand::RunAsEnableCommand()
934 {
935 int result = OHOS::ERR_OK;
936 int counter = 0;
937 std::string bundleName = "";
938 std::string abilityName = "";
939 int32_t userId = Constants::UNSPECIFIED_USERID;
940 while (true) {
941 counter++;
942 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
943 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
944 if (optind < 0 || optind > argc_) {
945 return OHOS::ERR_INVALID_VALUE;
946 }
947
948 if (option == -1) {
949 if (counter == 1) {
950 // When scanning the first argument
951 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
952 // 'bm enable' with no option: bm enable
953 // 'bm enable' with a wrong argument: bm enable xxx
954 APP_LOGD("'bm enable' with no option.");
955 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
956 result = OHOS::ERR_INVALID_VALUE;
957 }
958 }
959 break;
960 }
961
962 if (option == '?') {
963 switch (optopt) {
964 case 'n': {
965 // 'bm enable -n' with no argument: bm enable -n
966 // 'bm enable --bundle-name' with no argument: bm enable --bundle-name
967 APP_LOGD("'bm enable -n' with no argument.");
968 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
969 result = OHOS::ERR_INVALID_VALUE;
970 break;
971 }
972 case 'a': {
973 // 'bm enable -a' with no argument: bm enable -a
974 // 'bm enable --ability-name' with no argument: bm enable --ability-name
975 APP_LOGD("'bm enable -a' with no argument.");
976 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
977 result = OHOS::ERR_INVALID_VALUE;
978 break;
979 }
980 case 'u': {
981 // 'bm enable -u' with no argument: bm enable -u
982 // 'bm enable --user-id' with no argument: bm enable --user-id
983 APP_LOGD("'bm enable -u' with no argument.");
984 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
985 result = OHOS::ERR_INVALID_VALUE;
986 break;
987 }
988 default: {
989 // 'bm enable' with an unknown option: bm enable -x
990 // 'bm enable' with an unknown option: bm enable -xxx
991 std::string unknownOption = "";
992 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
993 APP_LOGD("'bm enable' with an unknown option.");
994 resultReceiver_.append(unknownOptionMsg);
995 result = OHOS::ERR_INVALID_VALUE;
996 break;
997 }
998 }
999 break;
1000 }
1001
1002 switch (option) {
1003 case 'h': {
1004 // 'bm enable-h'
1005 // 'bm enable --help'
1006 APP_LOGD("'bm enable %{public}s'", argv_[optind - 1]);
1007 result = OHOS::ERR_INVALID_VALUE;
1008 break;
1009 }
1010 case 'n': {
1011 // 'bm enable -n <bundle-name>'
1012 // 'bm enable --bundle-name <bundle-name>'
1013 bundleName = optarg;
1014 break;
1015 }
1016 case 'a': {
1017 // 'bm enable -a <ability-name>'
1018 // 'bm enable --ability-name <ability-name>'
1019 abilityName = optarg;
1020 break;
1021 }
1022 case 'u': {
1023 // 'bm enable -u userId'
1024 // 'bm enable --user-id userId'
1025 APP_LOGD("'bm enable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1026 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1027 APP_LOGE("bm enable with error userId %{private}s", optarg);
1028 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1029 return OHOS::ERR_INVALID_VALUE;
1030 }
1031 break;
1032 }
1033 default: {
1034 result = OHOS::ERR_INVALID_VALUE;
1035 break;
1036 }
1037 }
1038 }
1039
1040 if (result == OHOS::ERR_OK) {
1041 if (resultReceiver_ == "" && bundleName.size() == 0) {
1042 // 'bm enable ...' with no bundle name option
1043 APP_LOGD("'bm enable' with no bundle name option.");
1044
1045 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1046 result = OHOS::ERR_INVALID_VALUE;
1047 }
1048 }
1049
1050 if (result != OHOS::ERR_OK) {
1051 resultReceiver_.append(HELP_MSG_ENABLE);
1052 } else {
1053 AbilityInfo abilityInfo;
1054 abilityInfo.name = abilityName;
1055 abilityInfo.bundleName = bundleName;
1056 bool enableResult = SetApplicationEnabledOperation(abilityInfo, true, userId);
1057 if (enableResult) {
1058 resultReceiver_ = STRING_ENABLE_BUNDLE_OK + "\n";
1059 } else {
1060 resultReceiver_ = STRING_ENABLE_BUNDLE_NG + "\n";
1061 }
1062 }
1063 return result;
1064 }
1065
RunAsDisableCommand()1066 ErrCode BundleManagerShellCommand::RunAsDisableCommand()
1067 {
1068 int result = OHOS::ERR_OK;
1069 int counter = 0;
1070 std::string bundleName = "";
1071 std::string abilityName = "";
1072 int32_t userId = Constants::UNSPECIFIED_USERID;
1073 while (true) {
1074 counter++;
1075 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1076 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1077 if (optind < 0 || optind > argc_) {
1078 return OHOS::ERR_INVALID_VALUE;
1079 }
1080 if (option == -1) {
1081 if (counter == 1) {
1082 // When scanning the first argument
1083 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1084 // 'bm disable' with no option: bm disable
1085 // 'bm disable' with a wrong argument: bm disable xxx
1086 APP_LOGD("'bm disable' with no option.");
1087 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1088 result = OHOS::ERR_INVALID_VALUE;
1089 }
1090 }
1091 break;
1092 }
1093 if (option == '?') {
1094 switch (optopt) {
1095 case 'n': {
1096 // 'bm disable -n' with no argument: bm disable -n
1097 // 'bm disable --bundle-name' with no argument: bm disable --bundle-name
1098 APP_LOGD("'bm disable' with no argument.");
1099 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1100 result = OHOS::ERR_INVALID_VALUE;
1101 break;
1102 }
1103 case 'a': {
1104 // 'bm disable -a' with no argument: bm disable -a
1105 // 'bm disable --ability-name' with no argument: bm disable --ability-name
1106 APP_LOGD("'bm disable -a' with no argument.");
1107 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1108 result = OHOS::ERR_INVALID_VALUE;
1109 break;
1110 }
1111 case 'u': {
1112 // 'bm disable -u' with no argument: bm disable -u
1113 // 'bm disable --user-id' with no argument: bm disable --user-id
1114 APP_LOGD("'bm disable -u' with no argument.");
1115 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1116 result = OHOS::ERR_INVALID_VALUE;
1117 break;
1118 }
1119 default: {
1120 // 'bm disable' with an unknown option: bm disable -x
1121 // 'bm disable' with an unknown option: bm disable -xxx
1122 std::string unknownOption = "";
1123 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1124 APP_LOGD("'bm disable' with an unknown option.");
1125 resultReceiver_.append(unknownOptionMsg);
1126 result = OHOS::ERR_INVALID_VALUE;
1127 break;
1128 }
1129 }
1130 break;
1131 }
1132 switch (option) {
1133 case 'h': {
1134 // 'bm disable -h'
1135 // 'bm disable --help'
1136 APP_LOGD("'bm disable %{public}s'", argv_[optind - 1]);
1137 result = OHOS::ERR_INVALID_VALUE;
1138 break;
1139 }
1140 case 'n': {
1141 // 'bm disable -n <bundle-name>'
1142 // 'bm disable --bundle-name <bundle-name>'
1143 bundleName = optarg;
1144 break;
1145 }
1146 case 'a': {
1147 // 'bm disable -a <ability-name>'
1148 // 'bm disable --ability-name <ability-name>'
1149 abilityName = optarg;
1150 break;
1151 }
1152 case 'u': {
1153 // 'bm disable -u userId'
1154 // 'bm disable --user-id userId'
1155 APP_LOGD("'bm disable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1156 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1157 APP_LOGE("bm disable with error userId %{private}s", optarg);
1158 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1159 return OHOS::ERR_INVALID_VALUE;
1160 }
1161 break;
1162 }
1163 default: {
1164 result = OHOS::ERR_INVALID_VALUE;
1165 break;
1166 }
1167 }
1168 }
1169 if (result == OHOS::ERR_OK) {
1170 if (resultReceiver_ == "" && bundleName.size() == 0) {
1171 // 'bm disable ...' with no bundle name option
1172 APP_LOGD("'bm disable' with no bundle name option.");
1173 resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1174 result = OHOS::ERR_INVALID_VALUE;
1175 }
1176 }
1177 if (result != OHOS::ERR_OK) {
1178 resultReceiver_.append(HELP_MSG_DISABLE);
1179 } else {
1180 AbilityInfo abilityInfo;
1181 abilityInfo.name = abilityName;
1182 abilityInfo.bundleName = bundleName;
1183 bool enableResult = SetApplicationEnabledOperation(abilityInfo, false, userId);
1184 if (enableResult) {
1185 resultReceiver_ = STRING_DISABLE_BUNDLE_OK + "\n";
1186 } else {
1187 resultReceiver_ = STRING_DISABLE_BUNDLE_NG + "\n";
1188 }
1189 }
1190 return result;
1191 }
1192
RunAsGetCommand()1193 ErrCode BundleManagerShellCommand::RunAsGetCommand()
1194 {
1195 int result = OHOS::ERR_OK;
1196 int counter = 0;
1197 while (true) {
1198 counter++;
1199 if (argc_ > MAX_ARGUEMENTS_NUMBER) {
1200 resultReceiver_.append(HELP_MSG_GET);
1201 return OHOS::ERR_INVALID_VALUE;
1202 }
1203 int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_GET.c_str(), LONG_OPTIONS_GET, nullptr);
1204 APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1205 if (optind < 0 || optind > argc_) {
1206 return OHOS::ERR_INVALID_VALUE;
1207 }
1208 if (option == -1) {
1209 if (counter == 1) {
1210 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1211 // 1.'bm get' with no option: bm get
1212 // 2.'bm get' with a wrong argument: bm get -xxx
1213 APP_LOGD("'bm get' %{public}s", HELP_MSG_NO_OPTION.c_str());
1214 resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1215 result = OHOS::ERR_INVALID_VALUE;
1216 }
1217 }
1218 break;
1219 }
1220 switch (option) {
1221 case 'h': {
1222 result = OHOS::ERR_INVALID_VALUE;
1223 break;
1224 }
1225 case 'u': {
1226 break;
1227 }
1228 default: {
1229 result = OHOS::ERR_INVALID_VALUE;
1230 resultReceiver_.append(STRING_INCORRECT_OPTION + "\n");
1231 break;
1232 }
1233 }
1234 }
1235 if (result != OHOS::ERR_OK) {
1236 resultReceiver_.append(HELP_MSG_GET);
1237 return result;
1238 }
1239 resultReceiver_.append(STRING_GET_UDID_OK + "\n");
1240 resultReceiver_.append(GetUdid() + "\n");
1241 return result;
1242 }
1243
RunAsQuickFixCommand()1244 ErrCode BundleManagerShellCommand::RunAsQuickFixCommand()
1245 {
1246 for (auto index = INDEX_OFFSET; index < argc_; ++index) {
1247 APP_LOGD("argv_[%{public}d]: %{public}s", index, argv_[index]);
1248 std::string opt = argv_[index];
1249 if ((opt == "-h") || (opt == "--help")) {
1250 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1251 return ERR_OK;
1252 } else if ((opt == "-a") || (opt == "--apply")) {
1253 if (index >= argc_ - INDEX_OFFSET) {
1254 resultReceiver_.append("error: option [--apply] is incorrect.\n");
1255 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1256 return ERR_INVALID_VALUE;
1257 }
1258
1259 std::string argKey = argv_[++index];
1260 index++;
1261 if (argKey == "-f" || argKey == "--file-path") {
1262 std::vector<std::string> quickFixFiles;
1263 // collect value of multi file-path.
1264 for (; index < argc_ && index >= INDEX_OFFSET; ++index) {
1265 if (argList_[index - INDEX_OFFSET] == "-q" || argList_[index - INDEX_OFFSET] == "--query" ||
1266 argList_[index - INDEX_OFFSET] == "-b" || argList_[index - INDEX_OFFSET] == "--bundle-name" ||
1267 argList_[index - INDEX_OFFSET] == "-a" || argList_[index - INDEX_OFFSET] == "--apply" ||
1268 argList_[index - INDEX_OFFSET] == "-f" || argList_[index - INDEX_OFFSET] == "--file-path") {
1269 break;
1270 }
1271 quickFixFiles.emplace_back(argList_[index - INDEX_OFFSET]);
1272 }
1273
1274 return QuickFixCommand::ApplyQuickFix(quickFixFiles, resultReceiver_);
1275 }
1276 } else if ((opt == "-q") || (opt == "--query")) {
1277 if (index >= argc_ - INDEX_OFFSET) {
1278 resultReceiver_.append("error: option [--query] is incorrect.\n");
1279 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1280 return ERR_INVALID_VALUE;
1281 }
1282
1283 std::string bundleName;
1284 std::string argKey = argv_[++index];
1285 std::string argValue = argv_[++index];
1286 if (argKey == "-b" || argKey == "--bundle-name") {
1287 bundleName = argValue;
1288 }
1289
1290 return QuickFixCommand::GetApplyedQuickFixInfo(bundleName, resultReceiver_);
1291 } else {
1292 resultReceiver_.append("error: unknown option.\n");
1293 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1294 return ERR_INVALID_VALUE;
1295 }
1296 }
1297
1298 resultReceiver_.append("error: parameter is not enough.\n");
1299 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1300 return ERR_INVALID_VALUE;
1301 }
1302
GetUdid() const1303 std::string BundleManagerShellCommand::GetUdid() const
1304 {
1305 char innerUdid[DEVICE_UDID_LENGTH] = { 0 };
1306 int ret = GetDevUdid(innerUdid, DEVICE_UDID_LENGTH);
1307 if (ret != 0) {
1308 APP_LOGE("GetUdid failed! ret = %{public}d.", ret);
1309 return STRING_GET_UDID_NG;
1310 }
1311 std::string udid = innerUdid;
1312 return udid;
1313 }
1314
DumpBundleList(int32_t userId) const1315 std::string BundleManagerShellCommand::DumpBundleList(int32_t userId) const
1316 {
1317 std::string dumpResults;
1318 bool dumpRet = bundleMgrProxy_->DumpInfos(
1319 DumpFlag::DUMP_BUNDLE_LIST, BUNDLE_NAME_EMPTY, userId, dumpResults);
1320 if (!dumpRet) {
1321 APP_LOGE("failed to dump bundle list.");
1322 }
1323 return dumpResults;
1324 }
1325
DumpBundleInfo(const std::string & bundleName,int32_t userId) const1326 std::string BundleManagerShellCommand::DumpBundleInfo(const std::string &bundleName, int32_t userId) const
1327 {
1328 std::string dumpResults;
1329 bool dumpRet = bundleMgrProxy_->DumpInfos(
1330 DumpFlag::DUMP_BUNDLE_INFO, bundleName, userId, dumpResults);
1331 if (!dumpRet) {
1332 APP_LOGE("failed to dump bundle info.");
1333 }
1334 return dumpResults;
1335 }
1336
DumpShortcutInfos(const std::string & bundleName,int32_t userId) const1337 std::string BundleManagerShellCommand::DumpShortcutInfos(const std::string &bundleName, int32_t userId) const
1338 {
1339 std::string dumpResults;
1340 bool dumpRet = bundleMgrProxy_->DumpInfos(
1341 DumpFlag::DUMP_SHORTCUT_INFO, bundleName, userId, dumpResults);
1342 if (!dumpRet) {
1343 APP_LOGE("failed to dump shortcut infos.");
1344 }
1345 return dumpResults;
1346 }
1347
DumpDistributedBundleInfo(const std::string & deviceId,const std::string & bundleName)1348 std::string BundleManagerShellCommand::DumpDistributedBundleInfo(
1349 const std::string &deviceId, const std::string &bundleName)
1350 {
1351 std::string dumpResults = "";
1352 DistributedBundleInfo distributedBundleInfo;
1353 bool dumpRet = bundleMgrProxy_->GetDistributedBundleInfo(deviceId, bundleName, distributedBundleInfo);
1354 if (!dumpRet) {
1355 APP_LOGE("failed to dump distributed bundleInfo.");
1356 } else {
1357 dumpResults.append("distributed bundleInfo");
1358 dumpResults.append(":\n");
1359 dumpResults.append(distributedBundleInfo.ToString());
1360 dumpResults.append("\n");
1361 }
1362 return dumpResults;
1363 }
1364
DumpDependentModuleNames(const std::string & bundleName,const std::string & moduleName) const1365 std::string BundleManagerShellCommand::DumpDependentModuleNames(
1366 const std::string &bundleName,
1367 const std::string &moduleName) const
1368 {
1369 APP_LOGD("DumpDependentModuleNames bundleName: %{public}s, moduleName: %{public}s",
1370 bundleName.c_str(), moduleName.c_str());
1371 std::string dumpResults = "";
1372 std::vector<std::string> dependentModuleNames;
1373 bool dumpRet = bundleMgrProxy_->GetAllDependentModuleNames(bundleName, moduleName, dependentModuleNames);
1374 if (!dumpRet) {
1375 APP_LOGE("failed to dump dependent module name.");
1376 } else {
1377 dumpResults.append("dependent moduleNames:");
1378 for (const auto &name : dependentModuleNames) {
1379 dumpResults.append("\n");
1380 dumpResults.append(name);
1381 }
1382 dumpResults.append("\n");
1383 }
1384 return dumpResults;
1385 }
1386
InstallOperation(const std::vector<std::string> & bundlePaths,InstallParam & installParam,int32_t waittingTime) const1387 int32_t BundleManagerShellCommand::InstallOperation(const std::vector<std::string> &bundlePaths,
1388 InstallParam &installParam, int32_t waittingTime) const
1389 {
1390 std::vector<std::string> realPathVec;
1391 for (auto &bundlePath : bundlePaths) {
1392 std::string absoluteBundlePath = "";
1393 if (bundlePath.empty()) {
1394 continue;
1395 }
1396 if (bundlePath.at(0) == '/') {
1397 // absolute path
1398 absoluteBundlePath.append(bundlePath);
1399 } else {
1400 // relative path
1401 char *currentPathPtr = getcwd(nullptr, 0);
1402
1403 if (currentPathPtr != nullptr) {
1404 absoluteBundlePath.append(currentPathPtr);
1405 absoluteBundlePath.append('/' + bundlePath);
1406
1407 free(currentPathPtr);
1408 currentPathPtr = nullptr;
1409 }
1410 }
1411 realPathVec.emplace_back(absoluteBundlePath);
1412 }
1413 std::vector<std::string> pathVec;
1414 for (const auto &path : realPathVec) {
1415 if (std::find(pathVec.begin(), pathVec.end(), path) == pathVec.end()) {
1416 pathVec.emplace_back(path);
1417 }
1418 }
1419 sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl(waittingTime));
1420 if (statusReceiver == nullptr) {
1421 APP_LOGE("statusReceiver is null");
1422 return IStatusReceiver::ERR_UNKNOWN;
1423 }
1424 sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1425 if (recipient == nullptr) {
1426 APP_LOGE("recipient is null");
1427 return IStatusReceiver::ERR_UNKNOWN;
1428 }
1429 bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1430 ErrCode res = bundleInstallerProxy_->StreamInstall(pathVec, installParam, statusReceiver);
1431 APP_LOGD("StreamInstall result is %{public}d", res);
1432 if (res == ERR_OK) {
1433 return statusReceiver->GetResultCode();
1434 }
1435 if (res == ERR_APPEXECFWK_INSTALL_PARAM_ERROR) {
1436 APP_LOGE("install param error");
1437 return IStatusReceiver::ERR_INSTALL_PARAM_ERROR;
1438 }
1439 if (res == ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR) {
1440 APP_LOGE("install internal error");
1441 return IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR;
1442 }
1443 if (res == ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID) {
1444 APP_LOGE("install invalid path");
1445 return IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID;
1446 }
1447 if (res == ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT) {
1448 APP_LOGE("install failed due to no space left");
1449 return IStatusReceiver::ERR_INSTALL_DISK_MEM_INSUFFICIENT;
1450 }
1451
1452 return res;
1453 }
1454
UninstallOperation(const std::string & bundleName,const std::string & moduleName,InstallParam & installParam) const1455 int32_t BundleManagerShellCommand::UninstallOperation(
1456 const std::string &bundleName, const std::string &moduleName, InstallParam &installParam) const
1457 {
1458 sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
1459 if (statusReceiver == nullptr) {
1460 APP_LOGE("statusReceiver is null");
1461 return IStatusReceiver::ERR_UNKNOWN;
1462 }
1463
1464 APP_LOGD("bundleName: %{public}s", bundleName.c_str());
1465 APP_LOGD("moduleName: %{public}s", moduleName.c_str());
1466
1467 sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1468 if (recipient == nullptr) {
1469 APP_LOGE("recipient is null");
1470 return IStatusReceiver::ERR_UNKNOWN;
1471 }
1472 bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1473 if (moduleName.size() != 0) {
1474 bundleInstallerProxy_->Uninstall(bundleName, moduleName, installParam, statusReceiver);
1475 } else {
1476 bundleInstallerProxy_->Uninstall(bundleName, installParam, statusReceiver);
1477 }
1478
1479 return statusReceiver->GetResultCode();
1480 }
1481
CleanBundleCacheFilesOperation(const std::string & bundleName,int32_t userId) const1482 bool BundleManagerShellCommand::CleanBundleCacheFilesOperation(const std::string &bundleName, int32_t userId) const
1483 {
1484 userId = BundleCommandCommon::GetCurrentUserId(userId);
1485 sptr<CleanCacheCallbackImpl> cleanCacheCallBack(new (std::nothrow) CleanCacheCallbackImpl());
1486 if (cleanCacheCallBack == nullptr) {
1487 APP_LOGE("cleanCacheCallBack is null");
1488 return false;
1489 }
1490 ErrCode cleanRet = bundleMgrProxy_->CleanBundleCacheFiles(bundleName, cleanCacheCallBack, userId);
1491 if (cleanRet == ERR_OK) {
1492 return cleanCacheCallBack->GetResultCode();
1493 }
1494 APP_LOGE("clean bundle cache files operation failed");
1495 return false;
1496 }
1497
CleanBundleDataFilesOperation(const std::string & bundleName,int32_t userId) const1498 bool BundleManagerShellCommand::CleanBundleDataFilesOperation(const std::string &bundleName, int32_t userId) const
1499 {
1500 APP_LOGD("bundleName: %{public}s, userId:%{public}d", bundleName.c_str(), userId);
1501 userId = BundleCommandCommon::GetCurrentUserId(userId);
1502 bool cleanRet = bundleMgrProxy_->CleanBundleDataFiles(bundleName, userId);
1503 if (!cleanRet) {
1504 APP_LOGE("clean bundle data files operation failed");
1505 }
1506 return cleanRet;
1507 }
1508
SetApplicationEnabledOperation(const AbilityInfo & abilityInfo,bool isEnable,int32_t userId) const1509 bool BundleManagerShellCommand::SetApplicationEnabledOperation(const AbilityInfo &abilityInfo,
1510 bool isEnable, int32_t userId) const
1511 {
1512 APP_LOGD("bundleName: %{public}s", abilityInfo.bundleName.c_str());
1513 userId = BundleCommandCommon::GetCurrentUserId(userId);
1514 int32_t ret;
1515 if (abilityInfo.name.size() == 0) {
1516 ret = bundleMgrProxy_->SetApplicationEnabled(abilityInfo.bundleName, isEnable, userId);
1517 } else {
1518 ret = bundleMgrProxy_->SetAbilityEnabled(abilityInfo, isEnable, userId);
1519 }
1520 if (ret != 0) {
1521 if (isEnable) {
1522 APP_LOGE("enable bundle failed");
1523 } else {
1524 APP_LOGE("disable bundle failed");
1525 }
1526 return false;
1527 }
1528 return true;
1529 }
1530 } // namespace AppExecFwk
1531 } // namespace OHOS
1532