• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "bundle_death_recipient.h"
27 #include "bundle_mgr_client.h"
28 #include "clean_cache_callback_host.h"
29 #include "if_system_ability_manager.h"
30 #include "iservice_registry.h"
31 #include "os_account_info.h"
32 #include "os_account_manager.h"
33 #include "parameter.h"
34 #include "status_receiver_impl.h"
35 #include "system_ability_definition.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 std::string SHORT_OPTIONS = "hp:rfn:m:a:cdu:";
46 const struct option LONG_OPTIONS[] = {
47     {"help", no_argument, nullptr, 'h'},
48     {"bundle-path", required_argument, nullptr, 'p'},
49     {"replace", no_argument, nullptr, 'r'},
50     {"bundle-name", required_argument, nullptr, 'n'},
51     {"module-name", required_argument, nullptr, 'm'},
52     {"ability-name", required_argument, nullptr, 'a'},
53     {"bundle-info", no_argument, nullptr, 'i'},
54     {"cache", no_argument, nullptr, 'c'},
55     {"data", no_argument, nullptr, 'd'},
56     {"user-id", required_argument, nullptr, 'u'},
57     {nullptr, 0, nullptr, 0},
58 };
59 
60 const std::string SHORT_OPTIONS_DUMP = "hn:aisu:d:";
61 const struct option LONG_OPTIONS_DUMP[] = {
62     {"help", no_argument, nullptr, 'h'},
63     {"bundle-name", required_argument, nullptr, 'n'},
64     {"all", no_argument, nullptr, 'a'},
65     {"bundle-info", no_argument, nullptr, 'i'},
66     {"shortcut-info", no_argument, nullptr, 's'},
67     {"user-id", required_argument, nullptr, 'u'},
68     {"device-id", required_argument, nullptr, 'd'},
69     {nullptr, 0, nullptr, 0},
70 };
71 
72 const std::string SHORT_OPTIONS_GET = "hu";
73 const struct option LONG_OPTIONS_GET[] = {
74     {"help", no_argument, nullptr, 'h'},
75     {"udid", no_argument, nullptr, 'u'},
76     {nullptr, 0, nullptr, 0},
77 };
78 }  // namespace
79 
80 class CleanCacheCallbackImpl : public CleanCacheCallbackHost {
81 public:
CleanCacheCallbackImpl()82     CleanCacheCallbackImpl()
83     {
84         signal_ = std::make_shared<std::promise<bool>>();
85     }
~CleanCacheCallbackImpl()86     virtual ~CleanCacheCallbackImpl() override
87     {}
88     virtual void OnCleanCacheFinished(bool error) override;
89     bool GetResultCode();
90 private:
91     std::shared_ptr<std::promise<bool>> signal_;
92     DISALLOW_COPY_AND_MOVE(CleanCacheCallbackImpl);
93 };
94 
OnCleanCacheFinished(bool error)95 void CleanCacheCallbackImpl::OnCleanCacheFinished(bool error)
96 {
97     if (signal_ != nullptr) {
98         signal_->set_value(!error);
99     }
100 }
101 
GetResultCode()102 bool CleanCacheCallbackImpl::GetResultCode()
103 {
104     if (signal_ != nullptr) {
105         auto future = signal_->get_future();
106         std::chrono::milliseconds span(MAX_WAITING_TIME);
107         if (future.wait_for(span) == std::future_status::timeout) {
108             return false;
109         }
110         return future.get();
111     }
112     return false;
113 }
114 
BundleManagerShellCommand(int argc,char * argv[])115 BundleManagerShellCommand::BundleManagerShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, TOOL_NAME)
116 {}
117 
CreateCommandMap()118 ErrCode BundleManagerShellCommand::CreateCommandMap()
119 {
120     commandMap_ = {
121         {"help", std::bind(&BundleManagerShellCommand::RunAsHelpCommand, this)},
122         {"install", std::bind(&BundleManagerShellCommand::RunAsInstallCommand, this)},
123         {"uninstall", std::bind(&BundleManagerShellCommand::RunAsUninstallCommand, this)},
124         {"dump", std::bind(&BundleManagerShellCommand::RunAsDumpCommand, this)},
125         {"clean", std::bind(&BundleManagerShellCommand::RunAsCleanCommand, this)},
126         {"enable", std::bind(&BundleManagerShellCommand::RunAsEnableCommand, this)},
127         {"disable", std::bind(&BundleManagerShellCommand::RunAsDisableCommand, this)},
128         {"get", std::bind(&BundleManagerShellCommand::RunAsGetCommand, this)},
129     };
130 
131     return OHOS::ERR_OK;
132 }
133 
CreateMessageMap()134 ErrCode BundleManagerShellCommand::CreateMessageMap()
135 {
136     messageMap_ = {
137         //  error + message
138         {
139             IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR,
140             "error: install internal error.",
141         },
142         {
143             IStatusReceiver::ERR_INSTALL_HOST_INSTALLER_FAILED,
144             "error: install host installer failed.",
145         },
146         {
147             IStatusReceiver::ERR_INSTALL_PARSE_FAILED,
148             "error: install parse failed.",
149         },
150         {
151             IStatusReceiver::ERR_INSTALL_VERSION_DOWNGRADE,
152             "error: install version downgrade.",
153         },
154         {
155             IStatusReceiver::ERR_INSTALL_VERIFICATION_FAILED,
156             "error: install verification failed.",
157         },
158         {
159             IStatusReceiver::ERR_INSTALL_FAILED_INVALID_SIGNATURE_FILE_PATH,
160             "error: signature file path is invalid.",
161         },
162         {
163             IStatusReceiver::ERR_INSTALL_FAILED_BAD_BUNDLE_SIGNATURE_FILE,
164             "error: cannot open signature file.",
165         },
166         {
167             IStatusReceiver::ERR_INSTALL_FAILED_NO_BUNDLE_SIGNATURE,
168             "error: no signature file.",
169         },
170         {
171             IStatusReceiver::ERR_INSTALL_FAILED_VERIFY_APP_PKCS7_FAIL,
172             "error: fail to verify pkcs7 file.",
173         },
174         {
175             IStatusReceiver::ERR_INSTALL_FAILED_PROFILE_PARSE_FAIL,
176             "error: fail to parse signature file.",
177         },
178         {
179             IStatusReceiver::ERR_INSTALL_FAILED_APP_SOURCE_NOT_TRUESTED,
180             "error: signature verification failed due to not trusted app source.",
181         },
182         {
183             IStatusReceiver::ERR_INSTALL_FAILED_BAD_DIGEST,
184             "error: signature verification failed due to not bad digest.",
185         },
186         {
187             IStatusReceiver::ERR_INSTALL_FAILED_BUNDLE_INTEGRITY_VERIFICATION_FAILURE,
188             "error: signature verification failed due to out of integrity.",
189         },
190         {
191             IStatusReceiver::ERR_INSTALL_FAILED_FILE_SIZE_TOO_LARGE,
192             "error: signature verification failed due to oversize file.",
193         },
194         {
195             IStatusReceiver::ERR_INSTALL_FAILED_BAD_PUBLICKEY,
196             "error: signature verification failed due to bad public key.",
197         },
198         {
199             IStatusReceiver::ERR_INSTALL_FAILED_BAD_BUNDLE_SIGNATURE,
200             "error: signature verification failed due to bad bundle signature.",
201         },
202         {
203             IStatusReceiver::ERR_INSTALL_FAILED_NO_PROFILE_BLOCK_FAIL,
204             "error: signature verification failed due to no profile block.",
205         },
206         {
207             IStatusReceiver::ERR_INSTALL_FAILED_BUNDLE_SIGNATURE_VERIFICATION_FAILURE,
208             "error: verify signature failed.",
209         },
210         {
211             IStatusReceiver::ERR_INSTALL_FAILED_VERIFY_SOURCE_INIT_FAIL,
212             "error: signature verification failed due to init source failed.",
213         },
214         {
215             IStatusReceiver::ERR_INSTALL_FAILED_INCOMPATIBLE_SIGNATURE,
216             "error: install incompatible signature info.",
217         },
218         {
219             IStatusReceiver::ERR_INSTALL_FAILED_INCONSISTENT_SIGNATURE,
220             "error: install sign info inconsistent.",
221         },
222         {
223             IStatusReceiver::ERR_INSTALL_PARAM_ERROR,
224             "error: install param error.",
225         },
226         {
227             IStatusReceiver::ERR_INSTALL_PERMISSION_DENIED,
228             "error: install permission denied.",
229         },
230         {
231             IStatusReceiver::ERR_INSTALL_ENTRY_ALREADY_EXIST,
232             "error: install entry already exist.",
233         },
234         {
235             IStatusReceiver::ERR_INSTALL_STATE_ERROR,
236             "error: install state error.",
237         },
238         {
239             IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID,
240             "error: install file path invalid.",
241         },
242         {
243             IStatusReceiver::ERR_INSTALL_INVALID_HAP_NAME,
244             "error: install invalid hap name.",
245         },
246         {
247             IStatusReceiver::ERR_INSTALL_INVALID_BUNDLE_FILE,
248             "error: install invalid bundle file.",
249         },
250         {
251             IStatusReceiver::ERR_INSTALL_INVALID_HAP_SIZE,
252             "error: install invalid hap size.",
253         },
254         {
255             IStatusReceiver::ERR_INSTALL_GENERATE_UID_ERROR,
256             "error: install generate uid error.",
257         },
258         {
259             IStatusReceiver::ERR_INSTALL_INSTALLD_SERVICE_ERROR,
260             "error: install installd service error.",
261         },
262         {
263             IStatusReceiver::ERR_INSTALL_BUNDLE_MGR_SERVICE_ERROR,
264             "error: install bundle mgr service error.",
265         },
266         {
267             IStatusReceiver::ERR_INSTALL_ALREADY_EXIST,
268             "error: install already exist.",
269         },
270         {
271             IStatusReceiver::ERR_INSTALL_BUNDLENAME_NOT_SAME,
272             "error: install bundle name not same",
273         },
274         {
275             IStatusReceiver::ERR_INSTALL_VERSIONCODE_NOT_SAME,
276             "error: install version code not same",
277         },
278         {
279             IStatusReceiver::ERR_INSTALL_VERSIONNAME_NOT_SAME,
280             "error: install version name not same",
281         },
282         {
283             IStatusReceiver::ERR_INSTALL_VENDOR_NOT_SAME,
284             "error: install vendor not same",
285         },
286         {
287             IStatusReceiver::ERR_INSTALL_RELEASETYPE_TARGET_NOT_SAME,
288             "error: install releaseType target not same",
289         },
290         {
291             IStatusReceiver::ERR_INSTALL_RELEASETYPE_COMPATIBLE_NOT_SAME,
292             "error: install releaseType compatible not same",
293         },
294         {
295             IStatusReceiver::ERR_INSTALL_VERSION_NOT_COMPATIBLE,
296             "error: install version not compatible",
297         },
298         {
299             IStatusReceiver::ERR_INSTALL_INVALID_NUMBER_OF_ENTRY_HAP,
300             "error: install invalid number of entry hap",
301         },
302         {
303             IStatusReceiver::ERR_INSTALL_DISK_MEM_INSUFFICIENT,
304             "error: install failed due to insufficient disk memory",
305         },
306         {
307             IStatusReceiver::ERR_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED,
308             "error: install failed due to grant request permissions failed",
309         },
310         {
311             IStatusReceiver::ERR_INSTALL_UPDATE_HAP_TOKEN_FAILED,
312             "error: install failed due to update hap token failed",
313         },
314         {
315             IStatusReceiver::ERR_INSTALL_SINGLETON_NOT_SAME,
316             "error: install failed due to singleton not same",
317         },
318         {
319             IStatusReceiver::ERR_INSTALL_ZERO_USER_WITH_NO_SINGLETON,
320             "error: install failed due to zero user can only install singleton app",
321         },
322         {
323             IStatusReceiver::ERR_INSTALL_CHECK_SYSCAP_FAILED,
324             "error: install failed due to check syscap filed",
325         },
326         {
327             IStatusReceiver::ERR_INSTALL_APPTYPE_NOT_SAME,
328             "error: install failed due to apptype not same",
329         },
330         {
331             IStatusReceiver::ERR_INSTALL_URI_DUPLICATE,
332             "error: install failed due to uri prefix duplicate",
333         },
334         {
335             IStatusReceiver::ERR_INSTALL_PARSE_UNEXPECTED,
336             "error: install parse unexpected.",
337         },
338         {
339             IStatusReceiver::ERR_INSTALL_PARSE_MISSING_BUNDLE,
340             "error: install parse missing bundle.",
341         },
342         {
343             IStatusReceiver::ERR_INSTALL_PARSE_MISSING_ABILITY,
344             "error: install parse missing ability.",
345         },
346         {
347             IStatusReceiver::ERR_INSTALL_PARSE_NO_PROFILE,
348             "error: install parse no profile.",
349         },
350         {
351             IStatusReceiver::ERR_INSTALL_PARSE_BAD_PROFILE,
352             "error: install parse bad profile.",
353         },
354         {
355             IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_PROP_TYPE_ERROR,
356             "error: install parse profile prop type error.",
357         },
358         {
359             IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_MISSING_PROP,
360             "error: install parse profile missing prop.",
361         },
362         {
363             IStatusReceiver::ERR_INSTALL_PARSE_PROFILE_PROP_CHECK_ERROR,
364             "error: install parse profile prop check error.",
365         },
366         {
367             IStatusReceiver::ERR_INSTALL_PARSE_PERMISSION_ERROR,
368             "error: install parse permission error.",
369         },
370         {
371             IStatusReceiver::ERR_INSTALL_PARSE_RPCID_FAILED,
372             "error: install parse syscap error.",
373         },
374         {
375             IStatusReceiver::ERR_INSTALLD_PARAM_ERROR,
376             "error: installd param error.",
377         },
378         {
379             IStatusReceiver::ERR_INSTALLD_GET_PROXY_ERROR,
380             "error: installd get proxy error.",
381         },
382         {
383             IStatusReceiver::ERR_INSTALLD_CREATE_DIR_FAILED,
384             "error: installd create dir failed.",
385         },
386         {
387             IStatusReceiver::ERR_INSTALLD_CREATE_DIR_EXIST,
388             "error: installd create dir exist.",
389         },
390         {
391             IStatusReceiver::ERR_INSTALLD_CHOWN_FAILED,
392             "error: installd chown failed.",
393         },
394         {
395             IStatusReceiver::ERR_INSTALLD_REMOVE_DIR_FAILED,
396             "error: installd remove dir failed.",
397         },
398         {
399             IStatusReceiver::ERR_INSTALLD_EXTRACT_FILES_FAILED,
400             "error: installd extract files failed.",
401         },
402         {
403             IStatusReceiver::ERR_INSTALLD_RNAME_DIR_FAILED,
404             "error: installd rename dir failed.",
405         },
406         {
407             IStatusReceiver::ERR_INSTALLD_CLEAN_DIR_FAILED,
408             "error: installd clean dir failed.",
409         },
410 
411         {
412             IStatusReceiver::ERR_UNINSTALL_SYSTEM_APP_ERROR,
413             "error: uninstall system app error.",
414         },
415         {
416             IStatusReceiver::ERR_UNINSTALL_KILLING_APP_ERROR,
417             "error: uninstall killing app error.",
418         },
419         {
420             IStatusReceiver::ERR_UNINSTALL_INVALID_NAME,
421             "error: uninstall invalid name.",
422         },
423         {
424             IStatusReceiver::ERR_UNINSTALL_PARAM_ERROR,
425             "error: uninstall param error.",
426         },
427         {
428             IStatusReceiver::ERR_UNINSTALL_PERMISSION_DENIED,
429             "error: uninstall permission denied.",
430         },
431         {
432             IStatusReceiver::ERR_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR,
433             "error: uninstall bundle mgr service error.",
434         },
435         {
436             IStatusReceiver::ERR_UNINSTALL_MISSING_INSTALLED_BUNDLE,
437             "error: uninstall missing installed bundle.",
438         },
439         {
440             IStatusReceiver::ERR_UNINSTALL_MISSING_INSTALLED_MODULE,
441             "error: uninstall missing installed module.",
442         },
443         {
444             IStatusReceiver::ERR_FAILED_SERVICE_DIED,
445             "error: bundle manager service is died",
446         },
447         {
448             IStatusReceiver::ERR_FAILED_GET_INSTALLER_PROXY,
449             "error: failed to get installer proxy",
450         },
451         {
452             IStatusReceiver::ERR_USER_NOT_EXIST,
453             "error: user not exist.",
454         },
455         {
456             IStatusReceiver::ERR_USER_NOT_INSTALL_HAP,
457             "error: user does not install the hap.",
458         },
459         {
460             IStatusReceiver::ERR_OPERATION_TIME_OUT,
461             "error: operation time out.",
462         },
463         {
464             IStatusReceiver::ERR_INSTALL_NOT_UNIQUE_DISTRO_MODULE_NAME,
465             "error: moduleName is not unique.",
466         },
467         {
468             IStatusReceiver::ERR_INSTALL_INCONSISTENT_MODULE_NAME,
469             "error: moduleName is inconsistent.",
470         },
471         {
472             IStatusReceiver::ERR_UNKNOWN,
473             "error: unknown.",
474         }
475     };
476 
477     return OHOS::ERR_OK;
478 }
479 
init()480 ErrCode BundleManagerShellCommand::init()
481 {
482     ErrCode result = OHOS::ERR_OK;
483 
484     if (!bundleMgrProxy_) {
485         bundleMgrProxy_ = GetBundleMgrProxy();
486         if (bundleMgrProxy_) {
487             if (!bundleInstallerProxy_) {
488                 bundleInstallerProxy_ = bundleMgrProxy_->GetBundleInstaller();
489             }
490         }
491     }
492 
493     if (!bundleMgrProxy_ || !bundleInstallerProxy_ || !bundleInstallerProxy_->AsObject()) {
494         result = OHOS::ERR_INVALID_VALUE;
495     }
496 
497     return result;
498 }
499 
GetBundleMgrProxy() const500 sptr<IBundleMgr> BundleManagerShellCommand::GetBundleMgrProxy() const
501 {
502     sptr<ISystemAbilityManager> systemAbilityManager =
503         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
504     if (!systemAbilityManager) {
505         APP_LOGE("failed to get system ability mgr.");
506         return nullptr;
507     }
508 
509     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
510     if (!remoteObject) {
511         APP_LOGE("failed to get bundle manager proxy.");
512         return nullptr;
513     }
514 
515     APP_LOGD("get bundle manager proxy success.");
516     return iface_cast<IBundleMgr>(remoteObject);
517 }
518 
GetInstallerProxy() const519 sptr<IBundleInstaller> BundleManagerShellCommand::GetInstallerProxy() const
520 {
521     sptr<IBundleMgr> bundleMgrProxy = GetBundleMgrProxy();
522     if (!bundleMgrProxy) {
523         APP_LOGE("bundle mgr proxy is nullptr.");
524         return nullptr;
525     }
526 
527     sptr<IBundleInstaller> installerProxy = bundleMgrProxy->GetBundleInstaller();
528     if (!installerProxy) {
529         APP_LOGE("failed to get bundle installer proxy.");
530         return nullptr;
531     }
532 
533     APP_LOGD("get bundle installer proxy success.");
534     return installerProxy;
535 }
536 
RunAsHelpCommand()537 ErrCode BundleManagerShellCommand::RunAsHelpCommand()
538 {
539     resultReceiver_.append(HELP_MSG);
540 
541     return OHOS::ERR_OK;
542 }
543 
RunAsInstallCommand()544 ErrCode BundleManagerShellCommand::RunAsInstallCommand()
545 {
546     int result = OHOS::ERR_OK;
547     InstallFlag installFlag = InstallFlag::NORMAL;
548     int option = -1;
549     int counter = 0;
550     std::vector<std::string> bundlePath;
551     int index = 0;
552     int32_t userId = Constants::ALL_USERID;
553     while (true) {
554         counter++;
555         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
556         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
557         if (optind < 0 || optind > argc_) {
558             return OHOS::ERR_INVALID_VALUE;
559         }
560         if (option == -1) {
561             if (counter == 1) {
562                 // When scanning the first argument
563                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
564                     // 'bm install' with no option: bm install
565                     // 'bm install' with a wrong argument: bm install xxx
566                     APP_LOGD("'bm install' with no option.");
567                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
568                     result = OHOS::ERR_INVALID_VALUE;
569                 }
570             }
571             break;
572         }
573 
574         if (option == '?') {
575             switch (optopt) {
576                 case 'p': {
577                     // 'bm install -p' with no argument: bm install -p
578                     // 'bm install --bundle-path' with no argument: bm install --bundle-path
579                     APP_LOGD("'bm install' with no argument.");
580                     resultReceiver_.append("error: option ");
581                     resultReceiver_.append("requires a value.\n");
582                     result = OHOS::ERR_INVALID_VALUE;
583                     break;
584                 }
585                 case 'u': {
586                     // 'bm install -u' with no argument: bm install -u
587                     // 'bm install --user-id' with no argument: bm install --user-id
588                     APP_LOGD("'bm install -u' with no argument.");
589                     resultReceiver_.append("error: option ");
590                     resultReceiver_.append("requires a value.\n");
591                     result = OHOS::ERR_INVALID_VALUE;
592                     break;
593                 }
594                 default: {
595                     // 'bm install' with an unknown option: bm install -x
596                     // 'bm install' with an unknown option: bm install -xxx
597                     std::string unknownOption = "";
598                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
599                     APP_LOGD("'bm install' with an unknown option.");
600                     resultReceiver_.append(unknownOptionMsg);
601                     result = OHOS::ERR_INVALID_VALUE;
602                     break;
603                 }
604             }
605             break;
606         }
607 
608         switch (option) {
609             case 'h': {
610                 // 'bm install -h'
611                 // 'bm install --help'
612                 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
613                 result = OHOS::ERR_INVALID_VALUE;
614                 break;
615             }
616             case 'p': {
617                 // 'bm install -p <bundle-file-path>'
618                 // 'bm install --bundle-path <bundle-file-path>'
619                 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
620                 if (GetBundlePath(optarg, bundlePath) != OHOS::ERR_OK) {
621                     APP_LOGD("'bm install' with no argument.");
622                     resultReceiver_.append("error: option ");
623                     resultReceiver_.append("requires a correct value.\n");
624                     return OHOS::ERR_INVALID_VALUE;
625                 }
626                 index = optind;
627                 break;
628             }
629             case 'r': {
630                 // 'bm install -r'
631                 // 'bm install --replace'
632                 installFlag = InstallFlag::REPLACE_EXISTING;
633                 break;
634             }
635             case 'u': {
636                 // 'bm install -p <bundle-file-path> -u userId'
637                 // 'bm install --bundle-path <bundle-file-path> --user-id userId'
638                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
639                 userId = atoi(optarg);
640                 break;
641             }
642             default: {
643                 result = OHOS::ERR_INVALID_VALUE;
644                 break;
645             }
646         }
647     }
648 
649     for (; index < argc_ && index >= INDEX_OFFSET; ++index) {
650         if (argList_[index - INDEX_OFFSET] == "-r" || argList_[index - INDEX_OFFSET] == "-f" ||
651             argList_[index - INDEX_OFFSET] == "--force" || argList_[index - INDEX_OFFSET] == "--replace" ||
652             argList_[index - INDEX_OFFSET] == "-p" || argList_[index - INDEX_OFFSET] == "--bundle-path" ||
653             argList_[index - INDEX_OFFSET] == "-u" || argList_[index - INDEX_OFFSET] == "--user-id") {
654             break;
655         }
656         if (GetBundlePath(argList_[index - INDEX_OFFSET], bundlePath) != OHOS::ERR_OK) {
657             bundlePath.clear();
658             APP_LOGD("'bm install' with error arguments.");
659             resultReceiver_.append("error value for the chosen option");
660             result = OHOS::ERR_INVALID_VALUE;
661         }
662     }
663 
664     for (auto &path : bundlePath) {
665         APP_LOGD("install hap path %{public}s", path.c_str());
666     }
667 
668     if (result == OHOS::ERR_OK) {
669         if (resultReceiver_ == "" && bundlePath.empty()) {
670             // 'bm install ...' with no bundle path option
671             APP_LOGD("'bm install' with no bundle path option.");
672             resultReceiver_.append(HELP_MSG_NO_BUNDLE_PATH_OPTION + "\n");
673             result = OHOS::ERR_INVALID_VALUE;
674         }
675     }
676 
677     if (result != OHOS::ERR_OK) {
678         resultReceiver_.append(HELP_MSG_INSTALL);
679     } else {
680         InstallParam installParam;
681         installParam.installFlag = installFlag;
682         installParam.userId = userId;
683         int32_t installResult = InstallOperation(bundlePath, installParam);
684         if (installResult == OHOS::ERR_OK) {
685             resultReceiver_ = STRING_INSTALL_BUNDLE_OK + "\n";
686         } else {
687             resultReceiver_ = STRING_INSTALL_BUNDLE_NG + "\n";
688             resultReceiver_.append(GetMessageFromCode(installResult));
689         }
690     }
691 
692     return result;
693 }
694 
GetBundlePath(const std::string & param,std::vector<std::string> & bundlePaths) const695 ErrCode BundleManagerShellCommand::GetBundlePath(const std::string& param,
696     std::vector<std::string>& bundlePaths) const
697 {
698     if (param.empty()) {
699         return OHOS::ERR_INVALID_VALUE;
700     }
701     if (param == "-f" || param == "--force" || param == "-r" || param == "--replace" || param == "-p" ||
702         param == "--bundle-path" || param == "-u" || param == "--user-id") {
703         return OHOS::ERR_INVALID_VALUE;
704     }
705     bundlePaths.emplace_back(param);
706     return OHOS::ERR_OK;
707 }
708 
RunAsUninstallCommand()709 ErrCode BundleManagerShellCommand::RunAsUninstallCommand()
710 {
711     int result = OHOS::ERR_OK;
712     int option = -1;
713     int counter = 0;
714     std::string bundleName = "";
715     std::string moduleName = "";
716     int32_t userId = Constants::ALL_USERID;
717     while (true) {
718         counter++;
719         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
720         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
721         if (optind < 0 || optind > argc_) {
722             return OHOS::ERR_INVALID_VALUE;
723         }
724         if (option == -1) {
725             if (counter == 1) {
726                 // When scanning the first argument
727                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
728                     // 'bm uninstall' with no option: bm uninstall
729                     // 'bm uninstall' with a wrong argument: bm uninstall xxx
730                     APP_LOGD("'bm uninstall' %{public}s", HELP_MSG_NO_OPTION.c_str());
731                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
732                     result = OHOS::ERR_INVALID_VALUE;
733                 }
734             }
735             break;
736         }
737 
738         if (option == '?') {
739             switch (optopt) {
740                 case 'n': {
741                     // 'bm uninstall -n' with no argument: bm uninstall -n
742                     // 'bm uninstall --bundle-name' with no argument: bm uninstall --bundle-name
743                     APP_LOGD("'bm uninstall -n' with no argument.");
744                     resultReceiver_.append("error: option ");
745                     resultReceiver_.append("requires a value.\n");
746                     result = OHOS::ERR_INVALID_VALUE;
747                     break;
748                 }
749                 case 'm': {
750                     // 'bm uninstall -m' with no argument: bm uninstall -m
751                     // 'bm uninstall --module-name' with no argument: bm uninstall --module-name
752                     APP_LOGD("'bm uninstall -m' with no argument.");
753                     resultReceiver_.append("error: option ");
754                     resultReceiver_.append("requires a value.\n");
755                     result = OHOS::ERR_INVALID_VALUE;
756                     break;
757                 }
758                 case 'u': {
759                     // 'bm uninstall -n <bundleName> -u userId'
760                     // 'bm uninstall --bundle-name <bundleName> --user-id userId'
761                     APP_LOGD("'bm uninstall -u' with no argument.");
762                     resultReceiver_.append("error: option ");
763                     resultReceiver_.append("requires a value.\n");
764                     result = OHOS::ERR_INVALID_VALUE;
765                     break;
766                 }
767                 default: {
768                     // 'bm uninstall' with an unknown option: bm uninstall -x
769                     // 'bm uninstall' with an unknown option: bm uninstall -xxx
770                     std::string unknownOption = "";
771                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
772                     APP_LOGD("'bm uninstall' with an unknown option.");
773                     resultReceiver_.append(unknownOptionMsg);
774                     result = OHOS::ERR_INVALID_VALUE;
775                     break;
776                 }
777             }
778             break;
779         }
780 
781         switch (option) {
782             case 'h': {
783                 // 'bm uninstall -h'
784                 // 'bm uninstall --help'
785                 APP_LOGD("'bm uninstall %{public}s'", argv_[optind - 1]);
786                 result = OHOS::ERR_INVALID_VALUE;
787                 break;
788             }
789             case 'n': {
790                 // 'bm uninstall -n xxx'
791                 // 'bm uninstall --bundle-name xxx'
792                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
793                 bundleName = optarg;
794                 break;
795             }
796             case 'm': {
797                 // 'bm uninstall -m xxx'
798                 // 'bm uninstall --module-name xxx'
799                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
800                 moduleName = optarg;
801                 break;
802             }
803             case 'u': {
804                 // 'bm uninstall -n <bundleName> -u userId'
805                 // 'bm uninstall --bundle-name <bundleName> --user-id userId'
806                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
807                 userId = atoi(optarg);
808                 break;
809             }
810             default: {
811                 result = OHOS::ERR_INVALID_VALUE;
812                 break;
813             }
814         }
815     }
816 
817     if (result == OHOS::ERR_OK) {
818         if (resultReceiver_ == "" && bundleName.size() == 0) {
819             // 'bm uninstall ...' with no bundle name option
820             APP_LOGD("'bm uninstall' with bundle name option.");
821             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
822             result = OHOS::ERR_INVALID_VALUE;
823         }
824     }
825 
826     if (result != OHOS::ERR_OK) {
827         resultReceiver_.append(HELP_MSG_UNINSTALL);
828     } else {
829         InstallParam installParam;
830         installParam.userId = userId;
831         int32_t uninstallResult = UninstallOperation(bundleName, moduleName, installParam);
832         if (uninstallResult == OHOS::ERR_OK) {
833             resultReceiver_ = STRING_UNINSTALL_BUNDLE_OK + "\n";
834         } else {
835             resultReceiver_ = STRING_UNINSTALL_BUNDLE_NG + "\n";
836             resultReceiver_.append(GetMessageFromCode(uninstallResult));
837         }
838     }
839 
840     return result;
841 }
842 
RunAsDumpCommand()843 ErrCode BundleManagerShellCommand::RunAsDumpCommand()
844 {
845     int result = OHOS::ERR_OK;
846     int option = -1;
847     int counter = 0;
848     std::string dumpResults = "";
849     std::string bundleName = "";
850     bool bundleDumpAll = false;
851     bool bundleDumpInfos = false;
852     bool bundleDumpInfo = false;
853     bool bundleDumpShortcut = false;
854     bool bundleDumpDistributedBundleInfo = false;
855     std::string deviceId = "";
856     int32_t userId = Constants::ALL_USERID;
857     while (true) {
858         counter++;
859         option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP.c_str(), LONG_OPTIONS_DUMP, nullptr);
860         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
861         if (optind < 0 || optind > argc_) {
862             return OHOS::ERR_INVALID_VALUE;
863         }
864         if (option == -1) {
865             if (counter == 1) {
866                 // When scanning the first argument
867                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
868                     // 'bm dump' with no option: bm dump
869                     // 'bm dump' with a wrong argument: bm dump xxx
870                     APP_LOGD("'bm dump' %{public}s", HELP_MSG_NO_OPTION.c_str());
871                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
872                     result = OHOS::ERR_INVALID_VALUE;
873                 }
874             }
875             break;
876         }
877         if (option == '?') {
878             switch (optopt) {
879                 case 'n': {
880                     // 'bm dump -n' with no argument: bm dump -n
881                     // 'bm dump --bundle-name' with no argument: bm dump --bundle-name
882                     APP_LOGD("'bm dump -n' with no argument.");
883                     resultReceiver_.append("error: option ");
884                     resultReceiver_.append("requires a value.\n");
885                     result = OHOS::ERR_INVALID_VALUE;
886                     break;
887                 }
888                 case 'u': {
889                     // 'bm dump -u' with no argument: bm dump -u
890                     // 'bm dump --user-id' with no argument: bm dump --user-id
891                     APP_LOGD("'bm dump -u' with no argument.");
892                     resultReceiver_.append("error: option ");
893                     resultReceiver_.append("requires a value.\n");
894                     result = OHOS::ERR_INVALID_VALUE;
895                     break;
896                 }
897                 case 'd': {
898                     // 'bm dump -d' with no argument: bm dump -d
899                     // 'bm dump --device-id' with no argument: bm dump --device-id
900                     APP_LOGD("'bm dump -d' with no argument.");
901                     resultReceiver_.append("error: option ");
902                     resultReceiver_.append("requires a value.\n");
903                     result = OHOS::ERR_INVALID_VALUE;
904                     break;
905                 }
906                 default: {
907                     // 'bm dump' with an unknown option: bm dump -x
908                     // 'bm dump' with an unknown option: bm dump -xxx
909                     std::string unknownOption = "";
910                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
911                     APP_LOGD("'bm dump' with an unknown option.");
912                     resultReceiver_.append(unknownOptionMsg);
913                     result = OHOS::ERR_INVALID_VALUE;
914                     break;
915                 }
916             }
917             break;
918         }
919         switch (option) {
920             case 'h': {
921                 // 'bm dump -h'
922                 // 'bm dump --help'
923                 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
924                 result = OHOS::ERR_INVALID_VALUE;
925                 break;
926             }
927             case 'a': {
928                 // 'bm dump -a'
929                 // 'bm dump --all'
930                 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
931                 bundleDumpAll = true;
932                 break;
933             }
934             case 'i': {
935                 // 'bm dump -i'
936                 // 'bm dump --bundle-info'
937                 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
938                 bundleDumpInfos = true;
939                 break;
940             }
941             case 'n': {
942                 // 'bm dump -n xxx'
943                 // 'bm dump --bundle-name xxx'
944                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
945                 bundleName = optarg;
946                 bundleDumpInfo = true;
947                 break;
948             }
949             case 's': {
950                 // 'bm dump -n xxx -s'
951                 // 'bm dump --bundle-name xxx --shortcut-info'
952                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
953                 bundleDumpShortcut = true;
954                 break;
955             }
956             case 'u': {
957                 // 'bm dump -n <bundleName> -u userId'
958                 // 'bm dump --bundle-name <bundleName> --user-id userId'
959                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
960                 userId = atoi(optarg);
961                 break;
962             }
963             case 'd': {
964                 // 'bm dump -n <bundleName> -d deviceId'
965                 // 'bm dump --bundle-name <bundleName> --device-id deviceId'
966                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
967                 deviceId = optarg;
968                 bundleDumpDistributedBundleInfo = true;
969                 break;
970             }
971             default: {
972                 result = OHOS::ERR_INVALID_VALUE;
973                 break;
974             }
975         }
976     }
977     if (result == OHOS::ERR_OK) {
978         if ((resultReceiver_ == "") && bundleDumpShortcut && (bundleName.size() == 0)) {
979             // 'bm dump -s ...' with no bundle name option
980             APP_LOGD("'bm dump -s' with no bundle name option.");
981             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
982             result = OHOS::ERR_INVALID_VALUE;
983         }
984         if ((resultReceiver_ == "") && bundleDumpDistributedBundleInfo && (bundleName.size() == 0)) {
985             // 'bm dump d ...' with no bundle name option
986             APP_LOGD("'bm dump -d' with no bundle name option.");
987             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
988             result = OHOS::ERR_INVALID_VALUE;
989         }
990     }
991     if (result != OHOS::ERR_OK) {
992         resultReceiver_.append(HELP_MSG_DUMP);
993     } else {
994         APP_LOGD("dumpResults: %{public}s", dumpResults.c_str());
995         if (bundleDumpShortcut) {
996             dumpResults = DumpShortcutInfos(bundleName, userId);
997         } else if (bundleDumpDistributedBundleInfo) {
998             dumpResults = DumpDistributedBundleInfo(deviceId, userId, bundleName);
999         } else if (bundleDumpAll) {
1000             dumpResults = DumpBundleList(userId);
1001         } else if (bundleDumpInfos) {
1002             dumpResults = DumpBundleInfos(userId);
1003         } else if (bundleDumpInfo) {
1004             dumpResults = DumpBundleInfo(bundleName, userId);
1005         }
1006         if (dumpResults.empty() || (dumpResults == "")) {
1007             dumpResults = HELP_MSG_DUMP_FAILED + "\n";
1008         }
1009         resultReceiver_.append(dumpResults);
1010     }
1011 
1012     return result;
1013 }
1014 
RunAsCleanCommand()1015 ErrCode BundleManagerShellCommand::RunAsCleanCommand()
1016 {
1017     int32_t result = OHOS::ERR_OK;
1018     int32_t option = -1;
1019     int32_t counter = 0;
1020     int32_t userId = Constants::UNSPECIFIED_USERID;
1021     bool cleanCache = false;
1022     bool cleanData = false;
1023     std::string bundleName = "";
1024     while (true) {
1025         counter++;
1026         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1027         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1028         if (optind < 0 || optind > argc_) {
1029             return OHOS::ERR_INVALID_VALUE;
1030         }
1031         if (option == -1) {
1032             if (counter == 1) {
1033                 // When scanning the first argument
1034                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1035                     // 'bm clean' with no option: bm clean
1036                     // 'bm clean' with a wrong argument: bm clean xxx
1037                     APP_LOGD("'bm clean' %{public}s", HELP_MSG_NO_OPTION.c_str());
1038 
1039                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1040                     result = OHOS::ERR_INVALID_VALUE;
1041                 }
1042             }
1043             break;
1044         }
1045 
1046         if (option == '?') {
1047             switch (optopt) {
1048                 case 'n': {
1049                     // 'bm clean -n' with no argument: bm clean -n
1050                     // 'bm clean --bundle-name' with no argument: bm clean --bundle-name
1051                     APP_LOGD("'bm clean -n' with no argument.");
1052                     resultReceiver_.append("error: option ");
1053                     resultReceiver_.append("requires a value.\n");
1054                     result = OHOS::ERR_INVALID_VALUE;
1055                     break;
1056                 }
1057                 case 'u': {
1058                     // 'bm clean -u' with no argument: bm clean -u
1059                     // 'bm clean --user-id' with no argument: bm clean --user-id
1060                     APP_LOGD("'bm clean -u' with no argument.");
1061                     resultReceiver_.append("error: option ");
1062                     resultReceiver_.append("requires a value.\n");
1063                     result = OHOS::ERR_INVALID_VALUE;
1064                     break;
1065                 }
1066                 default: {
1067                     // 'bm clean' with an unknown option: bm clear -x
1068                     // 'bm clean' with an unknown option: bm clear -xxx
1069                     std::string unknownOption = "";
1070                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1071                     APP_LOGD("'bm clean' with an unknown option.");
1072                     resultReceiver_.append(unknownOptionMsg);
1073                     result = OHOS::ERR_INVALID_VALUE;
1074                     break;
1075                 }
1076             }
1077             break;
1078         }
1079 
1080         switch (option) {
1081             case 'h': {
1082                 // 'bm clean -h'
1083                 // 'bm clean --help'
1084                 APP_LOGD("'bm clean %{public}s'", argv_[optind - 1]);
1085                 result = OHOS::ERR_INVALID_VALUE;
1086                 break;
1087             }
1088             case 'n': {
1089                 // 'bm clean -n xxx'
1090                 // 'bm clean --bundle-name xxx'
1091                 APP_LOGD("'bm clean %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1092                 bundleName = optarg;
1093                 break;
1094             }
1095             case 'c': {
1096                 // 'bm clean -c'
1097                 // 'bm clean --cache'
1098                 APP_LOGD("'bm clean %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
1099                 cleanCache = (cleanData == true) ? false : true;
1100                 break;
1101             }
1102             case 'd': {
1103                 // 'bm clean -d'
1104                 // 'bm clean --data'
1105                 APP_LOGD("'bm clean %{public}s '", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
1106                 cleanData = (cleanCache == true) ? false : true;
1107                 break;
1108             }
1109             case 'u': {
1110                 // 'bm clean -u userId'
1111                 // 'bm clean --user-id userId'
1112                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1113                 userId = atoi(optarg);
1114                 break;
1115             }
1116             default: {
1117                 result = OHOS::ERR_INVALID_VALUE;
1118                 break;
1119             }
1120         }
1121     }
1122 
1123     if (result == OHOS::ERR_OK) {
1124         if (resultReceiver_ == "" && bundleName.size() == 0) {
1125             // 'bm clean ...' with no bundle name option
1126             APP_LOGD("'bm clean' with no bundle name option.");
1127             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1128             result = OHOS::ERR_INVALID_VALUE;
1129         }
1130         if (!cleanCache && !cleanData) {
1131             APP_LOGD("'bm clean' with no '-c' or '-d' option.");
1132             resultReceiver_.append(HELP_MSG_NO_DATA_OR_CACHE_OPTION + "\n");
1133             result = OHOS::ERR_INVALID_VALUE;
1134         }
1135     }
1136 
1137     if (result != OHOS::ERR_OK) {
1138         resultReceiver_.append(HELP_MSG_CLEAN);
1139     } else {
1140         // bm clean -c
1141         if (cleanCache) {
1142             if (CleanBundleCacheFilesOperation(bundleName, userId)) {
1143                 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_OK + "\n";
1144             } else {
1145                 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_NG + "\n";
1146             }
1147         }
1148         // bm clean -d
1149         if (cleanData) {
1150             if (CleanBundleDataFilesOperation(bundleName, userId)) {
1151                 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_OK + "\n");
1152             } else {
1153                 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_NG + "\n");
1154             }
1155         }
1156     }
1157     return result;
1158 }
1159 
RunAsEnableCommand()1160 ErrCode BundleManagerShellCommand::RunAsEnableCommand()
1161 {
1162     int result = OHOS::ERR_OK;
1163     int option = -1;
1164     int counter = 0;
1165     std::string bundleName = "";
1166     std::string abilityName = "";
1167     int32_t userId = Constants::UNSPECIFIED_USERID;
1168     while (true) {
1169         counter++;
1170         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1171         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1172         if (optind < 0 || optind > argc_) {
1173             return OHOS::ERR_INVALID_VALUE;
1174         }
1175 
1176         if (option == -1) {
1177             if (counter == 1) {
1178                 // When scanning the first argument
1179                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1180                     // 'bm enable' with no option: bm enable
1181                     // 'bm enable' with a wrong argument: bm enable xxx
1182                     APP_LOGD("'bm enable' with no option.");
1183                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1184                     result = OHOS::ERR_INVALID_VALUE;
1185                 }
1186             }
1187             break;
1188         }
1189 
1190         if (option == '?') {
1191             switch (optopt) {
1192                 case 'n': {
1193                     // 'bm enable -n' with no argument: bm enable -n
1194                     // 'bm enable --bundle-name' with no argument: bm enable --bundle-name
1195                     APP_LOGD("'bm enable -n' with no argument.");
1196                     resultReceiver_.append("error: option ");
1197                     resultReceiver_.append("requires a value.\n");
1198                     result = OHOS::ERR_INVALID_VALUE;
1199                     break;
1200                 }
1201                 case 'a': {
1202                     // 'bm enable -a' with no argument: bm enable -a
1203                     // 'bm enable --ability-name' with no argument: bm enable --ability-name
1204                     APP_LOGD("'bm enable -a' with no argument.");
1205                     resultReceiver_.append("error: option ");
1206                     resultReceiver_.append("requires a value.\n");
1207                     result = OHOS::ERR_INVALID_VALUE;
1208                     break;
1209                 }
1210                 case 'u': {
1211                     // 'bm enable -u' with no argument: bm enable -u
1212                     // 'bm enable --user-id' with no argument: bm enable --user-id
1213                     APP_LOGD("'bm enable -u' with no argument.");
1214                     resultReceiver_.append("error: option ");
1215                     resultReceiver_.append("requires a value.\n");
1216                     result = OHOS::ERR_INVALID_VALUE;
1217                     break;
1218                 }
1219                 default: {
1220                     // 'bm enable' with an unknown option: bm enable -x
1221                     // 'bm enable' with an unknown option: bm enable -xxx
1222                     std::string unknownOption = "";
1223                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1224                     APP_LOGD("'bm enable' with an unknown option.");
1225                     resultReceiver_.append(unknownOptionMsg);
1226                     result = OHOS::ERR_INVALID_VALUE;
1227                     break;
1228                 }
1229             }
1230             break;
1231         }
1232 
1233         switch (option) {
1234             case 'h': {
1235                 // 'bm enable-h'
1236                 // 'bm enable --help'
1237                 APP_LOGD("'bm enable %{public}s'", argv_[optind - 1]);
1238                 result = OHOS::ERR_INVALID_VALUE;
1239                 break;
1240             }
1241             case 'n': {
1242                 // 'bm enable -n <bundle-name>'
1243                 // 'bm enable --bundle-name <bundle-name>'
1244                 bundleName = optarg;
1245                 break;
1246             }
1247             case 'a': {
1248                 // 'bm enable -a <ability-name>'
1249                 // 'bm enable --ability-name <ability-name>'
1250                 abilityName = optarg;
1251                 break;
1252             }
1253             case 'u': {
1254                 // 'bm enable -u userId'
1255                 // 'bm enable --user-id userId'
1256                 APP_LOGD("'bm enable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1257                 userId = atoi(optarg);
1258                 break;
1259             }
1260             default: {
1261                 result = OHOS::ERR_INVALID_VALUE;
1262                 break;
1263             }
1264         }
1265     }
1266 
1267     if (result == OHOS::ERR_OK) {
1268         if (resultReceiver_ == "" && bundleName.size() == 0) {
1269             // 'bm enable ...' with no bundle name option
1270             APP_LOGD("'bm enable' with no bundle name option.");
1271 
1272             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1273             result = OHOS::ERR_INVALID_VALUE;
1274         }
1275     }
1276 
1277     if (result != OHOS::ERR_OK) {
1278         resultReceiver_.append(HELP_MSG_ENABLE);
1279     } else {
1280         AbilityInfo abilityInfo;
1281         abilityInfo.name = abilityName;
1282         abilityInfo.bundleName = bundleName;
1283         bool enableResult = SetApplicationEnabledOperation(abilityInfo, true, userId);
1284         if (enableResult == true) {
1285             resultReceiver_ = STRING_ENABLE_BUNDLE_OK + "\n";
1286         } else {
1287             resultReceiver_ = STRING_ENABLE_BUNDLE_NG + "\n";
1288         }
1289     }
1290     return result;
1291 }
1292 
RunAsDisableCommand()1293 ErrCode BundleManagerShellCommand::RunAsDisableCommand()
1294 {
1295     int result = OHOS::ERR_OK;
1296     int option = -1;
1297     int counter = 0;
1298     std::string bundleName = "";
1299     std::string abilityName = "";
1300     int32_t userId = Constants::UNSPECIFIED_USERID;
1301     while (true) {
1302         counter++;
1303         option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1304         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1305         if (optind < 0 || optind > argc_) {
1306             return OHOS::ERR_INVALID_VALUE;
1307         }
1308         if (option == -1) {
1309             if (counter == 1) {
1310                 // When scanning the first argument
1311                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1312                     // 'bm disable' with no option: bm disable
1313                     // 'bm disable' with a wrong argument: bm disable xxx
1314                     APP_LOGD("'bm disable' with no option.");
1315                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1316                     result = OHOS::ERR_INVALID_VALUE;
1317                 }
1318             }
1319             break;
1320         }
1321         if (option == '?') {
1322             switch (optopt) {
1323                 case 'n': {
1324                     // 'bm disable -n' with no argument: bm disable -n
1325                     // 'bm disable --bundle-name' with no argument: bm disable --bundle-name
1326                     APP_LOGD("'bm disable' with no argument.");
1327                     resultReceiver_.append("error: option ");
1328                     resultReceiver_.append("requires a value.\n");
1329                     result = OHOS::ERR_INVALID_VALUE;
1330                     break;
1331                 }
1332                 case 'a': {
1333                     // 'bm disable -a' with no argument: bm disable -a
1334                     // 'bm disable --ability-name' with no argument: bm disable --ability-name
1335                     APP_LOGD("'bm disable -a' with no argument.");
1336                     resultReceiver_.append("error: option ");
1337                     resultReceiver_.append("requires a value.\n");
1338                     result = OHOS::ERR_INVALID_VALUE;
1339                     break;
1340                 }
1341                 case 'u': {
1342                     // 'bm disable -u' with no argument: bm disable -u
1343                     // 'bm disable --user-id' with no argument: bm disable --user-id
1344                     APP_LOGD("'bm disable -u' with no argument.");
1345                     resultReceiver_.append("error: option ");
1346                     resultReceiver_.append("requires a value.\n");
1347                     result = OHOS::ERR_INVALID_VALUE;
1348                     break;
1349                 }
1350                 default: {
1351                     // 'bm disable' with an unknown option: bm disable -x
1352                     // 'bm disable' with an unknown option: bm disable -xxx
1353                     std::string unknownOption = "";
1354                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1355                     APP_LOGD("'bm disable' with an unknown option.");
1356                     resultReceiver_.append(unknownOptionMsg);
1357                     result = OHOS::ERR_INVALID_VALUE;
1358                     break;
1359                 }
1360             }
1361             break;
1362         }
1363         switch (option) {
1364             case 'h': {
1365                 // 'bm disable -h'
1366                 // 'bm disable --help'
1367                 APP_LOGD("'bm disable %{public}s'", argv_[optind - 1]);
1368                 result = OHOS::ERR_INVALID_VALUE;
1369                 break;
1370             }
1371             case 'n': {
1372                 // 'bm disable -n <bundle-name>'
1373                 // 'bm disable --bundle-name <bundle-name>'
1374                 bundleName = optarg;
1375                 break;
1376             }
1377             case 'a': {
1378                 // 'bm disable -a <ability-name>'
1379                 // 'bm disable --ability-name <ability-name>'
1380                 abilityName = optarg;
1381                 break;
1382             }
1383             case 'u': {
1384                 // 'bm disable -u userId'
1385                 // 'bm disable --user-id userId'
1386                 APP_LOGD("'bm disable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1387                 userId = atoi(optarg);
1388                 break;
1389             }
1390             default: {
1391                 result = OHOS::ERR_INVALID_VALUE;
1392                 break;
1393             }
1394         }
1395     }
1396     if (result == OHOS::ERR_OK) {
1397         if (resultReceiver_ == "" && bundleName.size() == 0) {
1398             // 'bm disable ...' with no bundle name option
1399             APP_LOGD("'bm disable' with no bundle name option.");
1400             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1401             result = OHOS::ERR_INVALID_VALUE;
1402         }
1403     }
1404     if (result != OHOS::ERR_OK) {
1405         resultReceiver_.append(HELP_MSG_DISABLE);
1406     } else {
1407         AbilityInfo abilityInfo;
1408         abilityInfo.name = abilityName;
1409         abilityInfo.bundleName = bundleName;
1410         bool enableResult = SetApplicationEnabledOperation(abilityInfo, false, userId);
1411         if (enableResult == true) {
1412             resultReceiver_ = STRING_DISABLE_BUNDLE_OK + "\n";
1413         } else {
1414             resultReceiver_ = STRING_DISABLE_BUNDLE_NG + "\n";
1415         }
1416     }
1417     return result;
1418 }
1419 
RunAsGetCommand()1420 ErrCode BundleManagerShellCommand::RunAsGetCommand()
1421 {
1422     int result = OHOS::ERR_OK;
1423     int option = -1;
1424     int counter = 0;
1425     while (true) {
1426         counter++;
1427         if (argc_ > MAX_ARGUEMENTS_NUMBER) {
1428             resultReceiver_.append(HELP_MSG_GET);
1429             return OHOS::ERR_INVALID_VALUE;
1430         }
1431         option = getopt_long(argc_, argv_, SHORT_OPTIONS_GET.c_str(), LONG_OPTIONS_GET, nullptr);
1432         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1433         if (optind < 0 || optind > argc_) {
1434             return OHOS::ERR_INVALID_VALUE;
1435         }
1436         if (option == -1) {
1437             if (counter == 1) {
1438                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1439                     // 1.'bm get' with no option: bm get
1440                     // 2.'bm get' with a wrong argument: bm get -xxx
1441                     APP_LOGD("'bm get' %{public}s", HELP_MSG_NO_OPTION.c_str());
1442                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1443                     result = OHOS::ERR_INVALID_VALUE;
1444                 }
1445             }
1446             break;
1447         }
1448         switch (option) {
1449             case 'h': {
1450                 result = OHOS::ERR_INVALID_VALUE;
1451                 break;
1452             }
1453             case 'u': {
1454                 break;
1455             }
1456             default: {
1457                 result = OHOS::ERR_INVALID_VALUE;
1458                 resultReceiver_.append(STRING_INCORRECT_OPTION + "\n");
1459                 break;
1460             }
1461         }
1462     }
1463     if (result != OHOS::ERR_OK) {
1464         resultReceiver_.append(HELP_MSG_GET);
1465         return result;
1466     }
1467     resultReceiver_.append(STRING_GET_UDID_OK + "\n");
1468     resultReceiver_.append(GetUdid() + "\n");
1469     return result;
1470 }
1471 
GetUdid() const1472 std::string BundleManagerShellCommand::GetUdid() const
1473 {
1474     char innerUdid[DEVICE_UDID_LENGTH] = { 0 };
1475     int ret = GetDevUdid(innerUdid, DEVICE_UDID_LENGTH);
1476     if (ret != 0) {
1477         APP_LOGE("GetUdid failed! ret = %{public}d.", ret);
1478         return STRING_GET_UDID_NG;
1479     }
1480     std::string udid = innerUdid;
1481     return udid;
1482 }
1483 
DumpBundleList(int32_t userId) const1484 std::string BundleManagerShellCommand::DumpBundleList(int32_t userId) const
1485 {
1486     std::string dumpResults;
1487     bool dumpRet = bundleMgrProxy_->DumpInfos(
1488         DumpFlag::DUMP_BUNDLE_LIST, BUNDLE_NAME_EMPTY, userId, dumpResults);
1489     if (!dumpRet) {
1490         APP_LOGE("failed to dump bundle list.");
1491     }
1492     return dumpResults;
1493 }
1494 
DumpBundleInfos(int32_t userId) const1495 std::string BundleManagerShellCommand::DumpBundleInfos(int32_t userId) const
1496 {
1497     std::string dumpResults;
1498     bool dumpRet = bundleMgrProxy_->DumpInfos(
1499         DumpFlag::DUMP_ALL_BUNDLE_INFO, BUNDLE_NAME_EMPTY, userId, dumpResults);
1500     if (!dumpRet) {
1501         APP_LOGE("failed to dump bundle infos.");
1502     }
1503     return dumpResults;
1504 }
1505 
DumpBundleInfo(const std::string & bundleName,int32_t userId) const1506 std::string BundleManagerShellCommand::DumpBundleInfo(const std::string &bundleName, int32_t userId) const
1507 {
1508     std::string dumpResults;
1509     bool dumpRet = bundleMgrProxy_->DumpInfos(
1510         DumpFlag::DUMP_BUNDLE_INFO, bundleName, userId, dumpResults);
1511     if (!dumpRet) {
1512         APP_LOGE("failed to dump bundle info.");
1513     }
1514     return dumpResults;
1515 }
1516 
DumpShortcutInfos(const std::string & bundleName,int32_t userId) const1517 std::string BundleManagerShellCommand::DumpShortcutInfos(const std::string &bundleName, int32_t userId) const
1518 {
1519     std::string dumpResults;
1520     bool dumpRet = bundleMgrProxy_->DumpInfos(
1521         DumpFlag::DUMP_SHORTCUT_INFO, bundleName, userId, dumpResults);
1522     if (!dumpRet) {
1523         APP_LOGE("failed to dump shortcut infos.");
1524     }
1525     return dumpResults;
1526 }
1527 
DumpDistributedBundleInfo(const std::string & deviceId,int32_t userId,const std::string & bundleName)1528 std::string BundleManagerShellCommand::DumpDistributedBundleInfo(const std::string &deviceId,
1529     int32_t userId, const std::string &bundleName)
1530 {
1531     std::string dumpResults = "";
1532     DistributedBundleInfo bundleInfo;
1533     bool dumpRet = bundleMgrProxy_->GetDistributedBundleInfo(deviceId, userId, bundleName, bundleInfo);
1534     if (!dumpRet) {
1535         APP_LOGE("failed to dump distributed bundleInfo.");
1536     } else {
1537         dumpResults.append("distributed bundleInfo");
1538         dumpResults.append(":\n");
1539         dumpResults.append(bundleInfo.ToString());
1540         dumpResults.append("\n");
1541     }
1542     return dumpResults;
1543 }
1544 
InstallOperation(const std::vector<std::string> & bundlePaths,InstallParam & installParam) const1545 int32_t BundleManagerShellCommand::InstallOperation(const std::vector<std::string> &bundlePaths,
1546     InstallParam &installParam) const
1547 {
1548     std::vector<std::string> realPathVec;
1549     for (auto &bundlePath : bundlePaths) {
1550         std::string absoluteBundlePath = "";
1551         if (bundlePath.empty()) {
1552             continue;
1553         }
1554         if (bundlePath.at(0) == '/') {
1555             // absolute path
1556             absoluteBundlePath.append(bundlePath);
1557         } else {
1558             // relative path
1559             char *currentPathPtr = getcwd(nullptr, 0);
1560 
1561             if (currentPathPtr != nullptr) {
1562                 absoluteBundlePath.append(currentPathPtr);
1563                 absoluteBundlePath.append('/' + bundlePath);
1564 
1565                 free(currentPathPtr);
1566                 currentPathPtr = nullptr;
1567             }
1568         }
1569         realPathVec.emplace_back(absoluteBundlePath);
1570     }
1571 
1572     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
1573     if (statusReceiver == nullptr) {
1574         APP_LOGE("statusReceiver is null");
1575         return IStatusReceiver::ERR_UNKNOWN;
1576     }
1577     sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1578     if (recipient == nullptr) {
1579         APP_LOGE("recipient is null");
1580         return IStatusReceiver::ERR_UNKNOWN;
1581     }
1582     bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1583     bundleInstallerProxy_->Install(realPathVec, installParam, statusReceiver);
1584     return statusReceiver->GetResultCode();
1585 }
1586 
UninstallOperation(const std::string & bundleName,const std::string & moduleName,InstallParam & installParam) const1587 int32_t BundleManagerShellCommand::UninstallOperation(
1588     const std::string &bundleName, const std::string &moduleName, InstallParam &installParam) const
1589 {
1590     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
1591     if (statusReceiver == nullptr) {
1592         APP_LOGE("statusReceiver is null");
1593         return IStatusReceiver::ERR_UNKNOWN;
1594     }
1595 
1596     APP_LOGD("bundleName: %{public}s", bundleName.c_str());
1597     APP_LOGD("moduleName: %{public}s", moduleName.c_str());
1598 
1599     sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1600     if (recipient == nullptr) {
1601         APP_LOGE("recipient is null");
1602         return IStatusReceiver::ERR_UNKNOWN;
1603     }
1604     bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1605     if (moduleName.size() != 0) {
1606         bundleInstallerProxy_->Uninstall(bundleName, moduleName, installParam, statusReceiver);
1607     } else {
1608         bundleInstallerProxy_->Uninstall(bundleName, installParam, statusReceiver);
1609     }
1610 
1611     return statusReceiver->GetResultCode();
1612 }
1613 
CleanBundleCacheFilesOperation(const std::string & bundleName,int32_t userId) const1614 bool BundleManagerShellCommand::CleanBundleCacheFilesOperation(const std::string &bundleName, int32_t userId) const
1615 {
1616     userId = GetCurrentUserId(userId);
1617     sptr<CleanCacheCallbackImpl> cleanCacheCallBack(new (std::nothrow) CleanCacheCallbackImpl());
1618     if (cleanCacheCallBack == nullptr) {
1619         APP_LOGE("cleanCacheCallBack is null");
1620         return false;
1621     }
1622     bool cleanRet = bundleMgrProxy_->CleanBundleCacheFiles(bundleName, cleanCacheCallBack, userId);
1623     if (cleanRet) {
1624         return cleanCacheCallBack->GetResultCode();
1625     }
1626     APP_LOGE("clean bundle cache files operation failed");
1627     return cleanRet;
1628 }
1629 
CleanBundleDataFilesOperation(const std::string & bundleName,int32_t userId) const1630 bool BundleManagerShellCommand::CleanBundleDataFilesOperation(const std::string &bundleName, int32_t userId) const
1631 {
1632     APP_LOGD("bundleName: %{public}s, userId:%{public}d", bundleName.c_str(), userId);
1633     userId = GetCurrentUserId(userId);
1634     bool cleanRet = bundleMgrProxy_->CleanBundleDataFiles(bundleName, userId);
1635     if (!cleanRet) {
1636         APP_LOGE("clean bundle data files operation failed");
1637     }
1638     return cleanRet;
1639 }
1640 
SetApplicationEnabledOperation(const AbilityInfo & abilityInfo,bool isEnable,int32_t userId) const1641 bool BundleManagerShellCommand::SetApplicationEnabledOperation(const AbilityInfo &abilityInfo,
1642     bool isEnable, int32_t userId) const
1643 {
1644     APP_LOGD("bundleName: %{public}s", abilityInfo.bundleName.c_str());
1645     userId = GetCurrentUserId(userId);
1646     bool ret = false;
1647     if (abilityInfo.name.size() == 0) {
1648         ret = bundleMgrProxy_->SetApplicationEnabled(abilityInfo.bundleName, isEnable, userId);
1649     } else {
1650         ret = bundleMgrProxy_->SetAbilityEnabled(abilityInfo, isEnable, userId);
1651     }
1652     if (!ret) {
1653         if (isEnable) {
1654             APP_LOGE("enable bundle failed");
1655         } else {
1656             APP_LOGE("disable bundle failed");
1657         }
1658     }
1659     return ret;
1660 }
1661 
GetCurrentUserId(int32_t userId) const1662 int32_t BundleManagerShellCommand::GetCurrentUserId(int32_t userId) const
1663 {
1664     if (userId == Constants::UNSPECIFIED_USERID) {
1665         std::vector<int> activeIds;
1666         int32_t ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(activeIds);
1667         if (ret != 0) {
1668             APP_LOGE("QueryActiveOsAccountIds failed! ret = %{public}d.", ret);
1669             return userId;
1670         }
1671         if (activeIds.empty()) {
1672             APP_LOGE("QueryActiveOsAccountIds activeIds empty");
1673             return userId;
1674         }
1675         return activeIds[0];
1676     }
1677     return userId;
1678 }
1679 }  // namespace AppExecFwk
1680 }  // namespace OHOS
1681