• 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 "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 "json_serializer.h"
33 #include "nlohmann/json.hpp"
34 #include "parameter.h"
35 #include "quick_fix_command.h"
36 #include "status_receiver_impl.h"
37 #include "string_ex.h"
38 
39 namespace OHOS {
40 namespace AppExecFwk {
41 namespace {
42 const std::string BUNDLE_NAME_EMPTY = "";
43 const std::string OVERLAY_MODULE_INFOS = "overlayModuleInfos";
44 const std::string OVERLAY_BUNDLE_INFOS = "overlayBundleInfos";
45 const std::string OVERLAY_MODULE_INFO = "overlayModuleInfo";
46 const std::string SHARED_BUNDLE_INFO = "sharedBundleInfo";
47 const std::string DEPENDENCIES = "dependencies";
48 const int32_t INDEX_OFFSET = 2;
49 const int32_t MIN_FILE_SIZE = 2;
50 const int32_t MAX_WAITING_TIME = 3000;
51 const int32_t DEVICE_UDID_LENGTH = 65;
52 const int32_t MAX_ARGUEMENTS_NUMBER = 3;
53 const int32_t MAX_OVERLAY_ARGUEMENTS_NUMBER = 8;
54 const int32_t MINIMUM_WAITTING_TIME = 180; // 3 mins
55 const int32_t MAXIMUM_WAITTING_TIME = 600; // 10 mins
56 
57 const std::string SHORT_OPTIONS = "hp:rn:m:a:cdu:w:s:v:";
58 const struct option LONG_OPTIONS[] = {
59     {"help", no_argument, nullptr, 'h'},
60     {"bundle-path", required_argument, nullptr, 'p'},
61     {"replace", no_argument, nullptr, 'r'},
62     {"bundle-name", required_argument, nullptr, 'n'},
63     {"module-name", required_argument, nullptr, 'm'},
64     {"ability-name", required_argument, nullptr, 'a'},
65     {"bundle-info", no_argument, nullptr, 'i'},
66     {"cache", no_argument, nullptr, 'c'},
67     {"data", no_argument, nullptr, 'd'},
68     {"is-removable", required_argument, nullptr, 'i'},
69     {"user-id", required_argument, nullptr, 'u'},
70     {"waitting-time", required_argument, nullptr, 'w'},
71     {"keep-data", no_argument, nullptr, 'k'},
72     {"shared-bundle-dir-path", required_argument, nullptr, 's'},
73     {"verify-code-signature-path", required_argument, nullptr, 'v'},
74     {nullptr, 0, nullptr, 0},
75 };
76 
77 const std::string UNINSTALL_OPTIONS = "hn:km:u:v:s";
78 const struct option UNINSTALL_LONG_OPTIONS[] = {
79     {"help", no_argument, nullptr, 'h'},
80     {"bundle-name", required_argument, nullptr, 'n'},
81     {"module-name", required_argument, nullptr, 'm'},
82     {"user-id", required_argument, nullptr, 'u'},
83     {"keep-data", no_argument, nullptr, 'k'},
84     {"version", required_argument, nullptr, 'v'},
85     {"shared", no_argument, nullptr, 's'},
86     {nullptr, 0, nullptr, 0},
87 };
88 
89 const std::string SHORT_OPTIONS_DUMP = "hn:aisu:d:";
90 const struct option LONG_OPTIONS_DUMP[] = {
91     {"help", no_argument, nullptr, 'h'},
92     {"bundle-name", required_argument, nullptr, 'n'},
93     {"all", no_argument, nullptr, 'a'},
94     {"bundle-info", no_argument, nullptr, 'i'},
95     {"shortcut-info", no_argument, nullptr, 's'},
96     {"user-id", required_argument, nullptr, 'u'},
97     {"device-id", required_argument, nullptr, 'd'},
98     {nullptr, 0, nullptr, 0},
99 };
100 
101 const std::string SHORT_OPTIONS_GET = "hu";
102 const struct option LONG_OPTIONS_GET[] = {
103     {"help", no_argument, nullptr, 'h'},
104     {"udid", no_argument, nullptr, 'u'},
105     {nullptr, 0, nullptr, 0},
106 };
107 
108 const std::string SHORT_OPTIONS_OVERLAY = "hb:m:t:u:";
109 const struct option LONG_OPTIONS_OVERLAY[] = {
110     {"help", no_argument, nullptr, 'h'},
111     {"bundle-name", required_argument, nullptr, 'b'},
112     {"module-name", required_argument, nullptr, 'm'},
113     {"target-module-name", required_argument, nullptr, 't'},
114     {"user-id", required_argument, nullptr, 'u'},
115     {nullptr, 0, nullptr, 0},
116 };
117 
118 const std::string SHORT_OPTIONS_OVERLAY_TARGET = "hb:m:u:";
119 const struct option LONG_OPTIONS_OVERLAY_TARGET[] = {
120     {"help", no_argument, nullptr, 'h'},
121     {"bundle-name", required_argument, nullptr, 'b'},
122     {"module-name", required_argument, nullptr, 'm'},
123     {"user-id", required_argument, nullptr, 'u'},
124     {nullptr, 0, nullptr, 0},
125 };
126 
127 const std::string SHORT_OPTIONS_DUMP_SHARED_DEPENDENCIES = "hn:m:";
128 const struct option LONG_OPTIONS_DUMP_SHARED_DEPENDENCIES[] = {
129     {"help", no_argument, nullptr, 'h'},
130     {"bundle-name", required_argument, nullptr, 'n'},
131     {"module-name", required_argument, nullptr, 'm'},
132     {nullptr, 0, nullptr, 0},
133 };
134 
135 const std::string SHORT_OPTIONS_DUMP_SHARED = "hn:a";
136 const struct option LONG_OPTIONS_DUMP_SHARED[] = {
137     {"help", no_argument, nullptr, 'h'},
138     {"bundle-name", required_argument, nullptr, 'n'},
139     {"all", no_argument, nullptr, 'a'},
140     {nullptr, 0, nullptr, 0},
141 };
142 }  // namespace
143 
144 class CleanCacheCallbackImpl : public CleanCacheCallbackHost {
145 public:
CleanCacheCallbackImpl()146     CleanCacheCallbackImpl() : signal_(std::make_shared<std::promise<bool>>())
147     {}
~CleanCacheCallbackImpl()148     virtual ~CleanCacheCallbackImpl() override
149     {}
150     virtual void OnCleanCacheFinished(bool error) override;
151     bool GetResultCode();
152 private:
153     std::shared_ptr<std::promise<bool>> signal_;
154     DISALLOW_COPY_AND_MOVE(CleanCacheCallbackImpl);
155 };
156 
OnCleanCacheFinished(bool error)157 void CleanCacheCallbackImpl::OnCleanCacheFinished(bool error)
158 {
159     if (signal_ != nullptr) {
160         signal_->set_value(error);
161     }
162 }
163 
GetResultCode()164 bool CleanCacheCallbackImpl::GetResultCode()
165 {
166     if (signal_ != nullptr) {
167         auto future = signal_->get_future();
168         std::chrono::milliseconds span(MAX_WAITING_TIME);
169         if (future.wait_for(span) == std::future_status::timeout) {
170             return false;
171         }
172         return future.get();
173     }
174     return false;
175 }
176 
BundleManagerShellCommand(int argc,char * argv[])177 BundleManagerShellCommand::BundleManagerShellCommand(int argc, char *argv[]) : ShellCommand(argc, argv, TOOL_NAME)
178 {}
179 
CreateCommandMap()180 ErrCode BundleManagerShellCommand::CreateCommandMap()
181 {
182     commandMap_ = {
183         {"help", std::bind(&BundleManagerShellCommand::RunAsHelpCommand, this)},
184         {"install", std::bind(&BundleManagerShellCommand::RunAsInstallCommand, this)},
185         {"uninstall", std::bind(&BundleManagerShellCommand::RunAsUninstallCommand, this)},
186         {"dump", std::bind(&BundleManagerShellCommand::RunAsDumpCommand, this)},
187         {"clean", std::bind(&BundleManagerShellCommand::RunAsCleanCommand, this)},
188         {"enable", std::bind(&BundleManagerShellCommand::RunAsEnableCommand, this)},
189         {"disable", std::bind(&BundleManagerShellCommand::RunAsDisableCommand, this)},
190         {"get", std::bind(&BundleManagerShellCommand::RunAsGetCommand, this)},
191         {"quickfix", std::bind(&BundleManagerShellCommand::RunAsQuickFixCommand, this)},
192         {"dump-overlay", std::bind(&BundleManagerShellCommand::RunAsDumpOverlay, this)},
193         {"dump-target-overlay", std::bind(&BundleManagerShellCommand::RunAsDumpTargetOverlay, this)},
194         {"dump-dependencies", std::bind(&BundleManagerShellCommand::RunAsDumpSharedDependenciesCommand, this)},
195         {"dump-shared", std::bind(&BundleManagerShellCommand::RunAsDumpSharedCommand, this)},
196     };
197 
198     return OHOS::ERR_OK;
199 }
200 
CreateMessageMap()201 ErrCode BundleManagerShellCommand::CreateMessageMap()
202 {
203     messageMap_ = BundleCommandCommon::bundleMessageMap_;
204     return OHOS::ERR_OK;
205 }
206 
Init()207 ErrCode BundleManagerShellCommand::Init()
208 {
209     ErrCode result = OHOS::ERR_OK;
210 
211     if (bundleMgrProxy_ == nullptr) {
212         bundleMgrProxy_ = BundleCommandCommon::GetBundleMgrProxy();
213         if (bundleMgrProxy_) {
214             if (bundleInstallerProxy_ == nullptr) {
215                 bundleInstallerProxy_ = bundleMgrProxy_->GetBundleInstaller();
216             }
217         }
218     }
219 
220     if ((bundleMgrProxy_ == nullptr) || (bundleInstallerProxy_ == nullptr) ||
221         (bundleInstallerProxy_->AsObject() == nullptr)) {
222         result = OHOS::ERR_INVALID_VALUE;
223     }
224 
225     return result;
226 }
227 
RunAsHelpCommand()228 ErrCode BundleManagerShellCommand::RunAsHelpCommand()
229 {
230     resultReceiver_.append(HELP_MSG);
231 
232     return OHOS::ERR_OK;
233 }
234 
IsInstallOption(int index) const235 bool BundleManagerShellCommand::IsInstallOption(int index) const
236 {
237     if (index >= argc_ || index < INDEX_OFFSET) {
238         return false;
239     }
240     if (argList_[index - INDEX_OFFSET] == "-r" || argList_[index - INDEX_OFFSET] == "--replace" ||
241         argList_[index - INDEX_OFFSET] == "-p" || argList_[index - INDEX_OFFSET] == "--bundle-path" ||
242         argList_[index - INDEX_OFFSET] == "-u" || argList_[index - INDEX_OFFSET] == "--user-id" ||
243         argList_[index - INDEX_OFFSET] == "-w" || argList_[index - INDEX_OFFSET] == "--waitting-time" ||
244         argList_[index - INDEX_OFFSET] == "-s" || argList_[index - INDEX_OFFSET] == "--shared-bundle-dir-path" ||
245         argList_[index - INDEX_OFFSET] == "-v" || argList_[index - INDEX_OFFSET] == "--verify-code-signature-path") {
246         return true;
247     }
248     return false;
249 }
250 
RunAsInstallCommand()251 ErrCode BundleManagerShellCommand::RunAsInstallCommand()
252 {
253     int result = OHOS::ERR_OK;
254     InstallFlag installFlag = InstallFlag::REPLACE_EXISTING;
255     int counter = 0;
256     std::vector<std::string> bundlePath;
257     std::vector<std::string> sharedBundleDirPaths;
258     int index = 0;
259     int hspIndex = 0;
260     int32_t userId = Constants::ALL_USERID;
261     int32_t waittingTime = MINIMUM_WAITTING_TIME;
262     std::string codeSignatureFilePath = "";
263     std::string moduleName = "";
264     while (true) {
265         counter++;
266         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
267         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
268         if (optind < 0 || optind > argc_) {
269             return OHOS::ERR_INVALID_VALUE;
270         }
271         if (option == -1) {
272             if (counter == 1) {
273                 // When scanning the first argument
274                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
275                     // 'bm install' with no option: bm install
276                     // 'bm install' with a wrong argument: bm install xxx
277                     APP_LOGD("'bm install' with no option.");
278                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
279                     result = OHOS::ERR_INVALID_VALUE;
280                 }
281             }
282             break;
283         }
284 
285         if (option == '?') {
286             switch (optopt) {
287                 case 'p': {
288                     // 'bm install -p' with no argument: bm install -p
289                     // 'bm install --bundle-path' with no argument: bm install --bundle-path
290                     APP_LOGD("'bm install' with no argument.");
291                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
292                     result = OHOS::ERR_INVALID_VALUE;
293                     break;
294                 }
295                 case 'u': {
296                     // 'bm install -u' with no argument: bm install -u
297                     // 'bm install --user-id' with no argument: bm install --user-id
298                     APP_LOGD("'bm install -u' with no argument.");
299                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
300                     result = OHOS::ERR_INVALID_VALUE;
301                     break;
302                 }
303                 case 'w': {
304                     // 'bm install -w' with no argument: bm install -w
305                     // 'bm install --waitting-time' with no argument: bm install --waitting-time
306                     APP_LOGD("'bm install -w' with no argument.");
307                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
308                     result = OHOS::ERR_INVALID_VALUE;
309                     break;
310                 }
311                 case 'v': {
312                     // 'bm install -v' with no argument: bm install -v
313                     // 'bm install --verify-code-signature-path' with no argument:
314                     // bm install --verify-code-signature-path
315                     APP_LOGD("'bm install -v' with no argument.");
316                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
317                     result = OHOS::ERR_INVALID_VALUE;
318                     break;
319                 }
320                 default: {
321                     // 'bm install' with an unknown option: bm install -x
322                     // 'bm install' with an unknown option: bm install -xxx
323                     std::string unknownOption = "";
324                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
325                     APP_LOGD("'bm install' with an unknown option.");
326                     resultReceiver_.append(unknownOptionMsg);
327                     result = OHOS::ERR_INVALID_VALUE;
328                     break;
329                 }
330             }
331             break;
332         }
333 
334         switch (option) {
335             case 'h': {
336                 // 'bm install -h'
337                 // 'bm install --help'
338                 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
339                 result = OHOS::ERR_INVALID_VALUE;
340                 break;
341             }
342             case 'p': {
343                 // 'bm install -p <bundle-file-path>'
344                 // 'bm install --bundle-path <bundle-file-path>'
345                 APP_LOGD("'bm install %{public}s'", argv_[optind - 1]);
346                 if (GetBundlePath(optarg, bundlePath) != OHOS::ERR_OK) {
347                     APP_LOGD("'bm install' with no argument.");
348                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
349                     return OHOS::ERR_INVALID_VALUE;
350                 }
351                 index = optind;
352                 break;
353             }
354             case 'r': {
355                 // 'bm install -r'
356                 // 'bm install --replace'
357                 installFlag = InstallFlag::REPLACE_EXISTING;
358                 break;
359             }
360             case 'u': {
361                 // 'bm install -p <bundle-file-path> -u userId'
362                 // 'bm install --bundle-path <bundle-file-path> --user-id userId'
363                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
364                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
365                     APP_LOGE("bm install with error userId %{private}s", optarg);
366                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
367                     return OHOS::ERR_INVALID_VALUE;
368                 }
369                 break;
370             }
371             case 'w': {
372                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
373                 if (!OHOS::StrToInt(optarg, waittingTime) || waittingTime < MINIMUM_WAITTING_TIME ||
374                     waittingTime > MAXIMUM_WAITTING_TIME) {
375                     APP_LOGE("bm install with error waittingTime %{private}s", optarg);
376                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
377                     return OHOS::ERR_INVALID_VALUE;
378                 }
379                 break;
380             }
381             case 's': {
382                 // 'bm install -s <hsp-dir-path>'
383                 // 'bm install --shared-bundle-dir-path <hsp-dir-path>'
384                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
385                 if (GetBundlePath(optarg, sharedBundleDirPaths) != OHOS::ERR_OK) {
386                     APP_LOGD("'bm install -s' with no argument.");
387                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
388                     return OHOS::ERR_INVALID_VALUE;
389                 }
390                 hspIndex = optind;
391                 break;
392             }
393             case 'v': {
394                 // 'bm install -v <code-signature-file-path>'
395                 // 'bm install --verify-code-signature-path <code-signature-file-path>'
396                 APP_LOGD("'bm install %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
397                 codeSignatureFilePath = optarg;
398                 if (codeSignatureFilePath.empty()) {
399                     APP_LOGD("'bm install -v' with no argument.");
400                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
401                     return OHOS::ERR_INVALID_VALUE;
402                 }
403                 break;
404             }
405             default: {
406                 result = OHOS::ERR_INVALID_VALUE;
407                 break;
408             }
409         }
410     }
411 
412     for (; index < argc_ && index >= INDEX_OFFSET; ++index) {
413         if (IsInstallOption(index)) {
414             break;
415         }
416         if (GetBundlePath(argList_[index - INDEX_OFFSET], bundlePath) != OHOS::ERR_OK) {
417             bundlePath.clear();
418             APP_LOGD("'bm install' with error arguments.");
419             resultReceiver_.append("error value for the chosen option");
420             result = OHOS::ERR_INVALID_VALUE;
421         }
422     }
423 
424     // hsp list
425     for (; hspIndex < argc_ && hspIndex >= INDEX_OFFSET; ++hspIndex) {
426         if (IsInstallOption(hspIndex)) {
427             break;
428         }
429         if (GetBundlePath(argList_[hspIndex - INDEX_OFFSET], sharedBundleDirPaths) != OHOS::ERR_OK) {
430             sharedBundleDirPaths.clear();
431             APP_LOGD("'bm install -s' with error arguments.");
432             resultReceiver_.append("error value for the chosen option");
433             result = OHOS::ERR_INVALID_VALUE;
434         }
435     }
436 
437     for (auto &path : bundlePath) {
438         APP_LOGD("install hap path %{private}s", path.c_str());
439     }
440 
441     for (auto &path : sharedBundleDirPaths) {
442         APP_LOGD("install hsp path %{private}s", path.c_str());
443     }
444 
445     if (result == OHOS::ERR_OK) {
446         if (resultReceiver_ == "" && bundlePath.empty() && sharedBundleDirPaths.empty()) {
447             // 'bm install ...' with no bundle path option
448             APP_LOGD("'bm install' with no bundle path option.");
449             resultReceiver_.append(HELP_MSG_NO_BUNDLE_PATH_OPTION + "\n");
450             result = OHOS::ERR_INVALID_VALUE;
451         }
452     }
453 
454     if ((!codeSignatureFilePath.empty()) && (bundlePath.size() > MIN_FILE_SIZE)) {
455         APP_LOGW("'bm install -v' does not support install multi hap or hsp simultaneously.");
456         resultReceiver_.append(HELP_MSG_NOT_SUPPORT_MULTI_HAP_OR_HSP_INSTALLATION);
457         result = OHOS::ERR_INVALID_VALUE;
458     }
459 
460     if (!sharedBundleDirPaths.empty() && !codeSignatureFilePath.empty()) {
461         APP_LOGW("the command 'bm install -s <sharedLibraryDir> -v signatureFilePath' is not supported.");
462         resultReceiver_.append(HELP_MSG_COMMAND_IS_NOT_SUPPORTED);
463         result = OHOS::ERR_INVALID_VALUE;
464     }
465 
466     if ((!codeSignatureFilePath.empty()) && (!bundlePath.empty())) {
467         if (!ObtainModuleNameFromBundlePaths(bundlePath, moduleName)) {
468             APP_LOGW("ObtainModuleNameFromBundlePaths failed");
469             resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
470             result = OHOS::ERR_INVALID_VALUE;
471         }
472     }
473 
474     if (result != OHOS::ERR_OK) {
475         resultReceiver_.append(HELP_MSG_INSTALL);
476     } else {
477         InstallParam installParam;
478         installParam.installFlag = installFlag;
479         installParam.userId = userId;
480         installParam.sharedBundleDirPaths = sharedBundleDirPaths;
481         if (!codeSignatureFilePath.empty() && !moduleName.empty()) {
482             installParam.verifyCodeParams.emplace(moduleName, codeSignatureFilePath);
483         }
484         int32_t installResult = InstallOperation(bundlePath, installParam, waittingTime);
485         if (installResult == OHOS::ERR_OK) {
486             resultReceiver_ = STRING_INSTALL_BUNDLE_OK + "\n";
487         } else {
488             resultReceiver_ = STRING_INSTALL_BUNDLE_NG + "\n";
489             resultReceiver_.append(GetMessageFromCode(installResult));
490         }
491     }
492 
493     return result;
494 }
495 
GetBundlePath(const std::string & param,std::vector<std::string> & bundlePaths) const496 ErrCode BundleManagerShellCommand::GetBundlePath(const std::string& param,
497     std::vector<std::string>& bundlePaths) const
498 {
499     if (param.empty()) {
500         return OHOS::ERR_INVALID_VALUE;
501     }
502     if (param == "-r" || param == "--replace" || param == "-p" ||
503         param == "--bundle-path" || param == "-u" || param == "--user-id" ||
504         param == "-w" || param == "--waitting-time" || param == "-v" || param == "--verify-code-signature-path") {
505         return OHOS::ERR_INVALID_VALUE;
506     }
507     bundlePaths.emplace_back(param);
508     return OHOS::ERR_OK;
509 }
510 
RunAsUninstallCommand()511 ErrCode BundleManagerShellCommand::RunAsUninstallCommand()
512 {
513     int result = OHOS::ERR_OK;
514     int counter = 0;
515     std::string bundleName = "";
516     std::string moduleName = "";
517     int32_t userId = Constants::ALL_USERID;
518     bool isKeepData = false;
519     bool isShared = false;
520     int32_t versionCode = Constants::ALL_VERSIONCODE;
521     while (true) {
522         counter++;
523         int32_t option = getopt_long(argc_, argv_, UNINSTALL_OPTIONS.c_str(), UNINSTALL_LONG_OPTIONS, nullptr);
524         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
525         if (optind < 0 || optind > argc_) {
526             return OHOS::ERR_INVALID_VALUE;
527         }
528         if (option == -1) {
529             if (counter == 1) {
530                 // When scanning the first argument
531                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
532                     // 'bm uninstall' with no option: bm uninstall
533                     // 'bm uninstall' with a wrong argument: bm uninstall xxx
534                     APP_LOGD("'bm uninstall' %{public}s", HELP_MSG_NO_OPTION.c_str());
535                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
536                     result = OHOS::ERR_INVALID_VALUE;
537                 }
538             }
539             break;
540         }
541 
542         if (option == '?') {
543             switch (optopt) {
544                 case 'n': {
545                     // 'bm uninstall -n' with no argument: bm uninstall -n
546                     // 'bm uninstall --bundle-name' with no argument: bm uninstall --bundle-name
547                     APP_LOGD("'bm uninstall -n' with no argument.");
548                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
549                     result = OHOS::ERR_INVALID_VALUE;
550                     break;
551                 }
552                 case 'm': {
553                     // 'bm uninstall -m' with no argument: bm uninstall -m
554                     // 'bm uninstall --module-name' with no argument: bm uninstall --module-name
555                     APP_LOGD("'bm uninstall -m' with no argument.");
556                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
557                     result = OHOS::ERR_INVALID_VALUE;
558                     break;
559                 }
560                 case 'u': {
561                     // 'bm uninstall -n <bundleName> -u userId'
562                     // 'bm uninstall --bundle-name <bundleName> --user-id userId'
563                     APP_LOGD("'bm uninstall -u' with no argument.");
564                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
565                     result = OHOS::ERR_INVALID_VALUE;
566                     break;
567                 }
568                 case 'k': {
569                     // 'bm uninstall -n <bundleName> -k'
570                     // 'bm uninstall --bundle-name <bundleName> --keep-data'
571                     APP_LOGD("'bm uninstall -k'");
572                     isKeepData = true;
573                     break;
574                 }
575                 case 's': {
576                     APP_LOGD("'bm uninstall -s'");
577                     isShared = true;
578                     break;
579                 }
580                 case 'v': {
581                     APP_LOGD("'bm uninstall -v'");
582                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
583                     result = OHOS::ERR_INVALID_VALUE;
584                     break;
585                 }
586                 default: {
587                     // 'bm uninstall' with an unknown option: bm uninstall -x
588                     // 'bm uninstall' with an unknown option: bm uninstall -xxx
589                     std::string unknownOption = "";
590                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
591                     APP_LOGD("'bm uninstall' with an unknown option.");
592                     resultReceiver_.append(unknownOptionMsg);
593                     result = OHOS::ERR_INVALID_VALUE;
594                     break;
595                 }
596             }
597             break;
598         }
599 
600         switch (option) {
601             case 'h': {
602                 // 'bm uninstall -h'
603                 // 'bm uninstall --help'
604                 APP_LOGD("'bm uninstall %{public}s'", argv_[optind - 1]);
605                 result = OHOS::ERR_INVALID_VALUE;
606                 break;
607             }
608             case 'n': {
609                 // 'bm uninstall -n xxx'
610                 // 'bm uninstall --bundle-name xxx'
611                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
612                 bundleName = optarg;
613                 break;
614             }
615             case 'm': {
616                 // 'bm uninstall -m xxx'
617                 // 'bm uninstall --module-name xxx'
618                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
619                 moduleName = optarg;
620                 break;
621             }
622             case 'u': {
623                 // 'bm uninstall -n <bundleName> -u userId'
624                 // 'bm uninstall --bundle-name <bundleName> --user-id userId'
625                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
626                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
627                     APP_LOGE("bm uninstall with error userId %{private}s", optarg);
628                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
629                     return OHOS::ERR_INVALID_VALUE;
630                 }
631                 break;
632             }
633             case 'k': {
634                 // 'bm uninstall -n <bundleName> -k'
635                 // 'bm uninstall --bundle-name <bundleName> --keep-data'
636                 APP_LOGD("'bm uninstall %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
637                 isKeepData = true;
638                 break;
639             }
640             case 's': {
641                 APP_LOGD("'bm uninstall -s'");
642                 isShared = true;
643                 break;
644             }
645             case 'v': {
646                 APP_LOGD("'bm uninstall %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
647                 if (!OHOS::StrToInt(optarg, versionCode) || versionCode < 0) {
648                     APP_LOGE("bm uninstall with error versionCode %{private}s", optarg);
649                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
650                     return OHOS::ERR_INVALID_VALUE;
651                 }
652                 break;
653             }
654             default: {
655                 result = OHOS::ERR_INVALID_VALUE;
656                 break;
657             }
658         }
659     }
660 
661     if (result == OHOS::ERR_OK) {
662         if (resultReceiver_ == "" && bundleName.size() == 0) {
663             // 'bm uninstall ...' with no bundle name option
664             APP_LOGD("'bm uninstall' with bundle name option.");
665             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
666             result = OHOS::ERR_INVALID_VALUE;
667         }
668     }
669     if (result != OHOS::ERR_OK) {
670         resultReceiver_.append(HELP_MSG_UNINSTALL);
671         return result;
672     }
673 
674     if (isShared) {
675         UninstallParam uninstallParam;
676         uninstallParam.bundleName = bundleName;
677         uninstallParam.versionCode = versionCode;
678         APP_LOGE("version code is %{public}d", versionCode);
679         int32_t uninstallResult = UninstallSharedOperation(uninstallParam);
680         if (uninstallResult == OHOS::ERR_OK) {
681             resultReceiver_ = STRING_UNINSTALL_BUNDLE_OK + "\n";
682         } else {
683             resultReceiver_ = STRING_UNINSTALL_BUNDLE_NG + "\n";
684             resultReceiver_.append(GetMessageFromCode(uninstallResult));
685         }
686     } else {
687         InstallParam installParam;
688         installParam.userId = userId;
689         installParam.isKeepData = isKeepData;
690         int32_t uninstallResult = UninstallOperation(bundleName, moduleName, installParam);
691         if (uninstallResult == OHOS::ERR_OK) {
692             resultReceiver_ = STRING_UNINSTALL_BUNDLE_OK + "\n";
693         } else {
694             resultReceiver_ = STRING_UNINSTALL_BUNDLE_NG + "\n";
695             resultReceiver_.append(GetMessageFromCode(uninstallResult));
696         }
697     }
698 
699     return result;
700 }
701 
RunAsDumpCommand()702 ErrCode BundleManagerShellCommand::RunAsDumpCommand()
703 {
704     int result = OHOS::ERR_OK;
705     int counter = 0;
706     std::string bundleName = "";
707     bool bundleDumpAll = false;
708     bool bundleDumpInfo = false;
709     bool bundleDumpShortcut = false;
710     bool bundleDumpDistributedBundleInfo = false;
711     std::string deviceId = "";
712     int32_t userId = Constants::ALL_USERID;
713     while (true) {
714         counter++;
715         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP.c_str(), LONG_OPTIONS_DUMP, nullptr);
716         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
717         if (optind < 0 || optind > argc_) {
718             return OHOS::ERR_INVALID_VALUE;
719         }
720         if (option == -1) {
721             if (counter == 1) {
722                 // When scanning the first argument
723                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
724                     // 'bm dump' with no option: bm dump
725                     // 'bm dump' with a wrong argument: bm dump xxx
726                     APP_LOGD("'bm dump' %{public}s", HELP_MSG_NO_OPTION.c_str());
727                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
728                     result = OHOS::ERR_INVALID_VALUE;
729                 }
730             }
731             break;
732         }
733         if (option == '?') {
734             switch (optopt) {
735                 case 'n': {
736                     // 'bm dump -n' with no argument: bm dump -n
737                     // 'bm dump --bundle-name' with no argument: bm dump --bundle-name
738                     APP_LOGD("'bm dump -n' with no argument.");
739                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
740                     result = OHOS::ERR_INVALID_VALUE;
741                     break;
742                 }
743                 case 'u': {
744                     // 'bm dump -u' with no argument: bm dump -u
745                     // 'bm dump --user-id' with no argument: bm dump --user-id
746                     APP_LOGD("'bm dump -u' with no argument.");
747                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
748                     result = OHOS::ERR_INVALID_VALUE;
749                     break;
750                 }
751                 case 'd': {
752                     // 'bm dump -d' with no argument: bm dump -d
753                     // 'bm dump --device-id' with no argument: bm dump --device-id
754                     APP_LOGD("'bm dump -d' with no argument.");
755                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
756                     result = OHOS::ERR_INVALID_VALUE;
757                     break;
758                 }
759                 default: {
760                     // 'bm dump' with an unknown option: bm dump -x
761                     // 'bm dump' with an unknown option: bm dump -xxx
762                     std::string unknownOption = "";
763                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
764                     APP_LOGD("'bm dump' with an unknown option.");
765                     resultReceiver_.append(unknownOptionMsg);
766                     result = OHOS::ERR_INVALID_VALUE;
767                     break;
768                 }
769             }
770             break;
771         }
772         switch (option) {
773             case 'h': {
774                 // 'bm dump -h'
775                 // 'bm dump --help'
776                 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
777                 result = OHOS::ERR_INVALID_VALUE;
778                 break;
779             }
780             case 'a': {
781                 // 'bm dump -a'
782                 // 'bm dump --all'
783                 APP_LOGD("'bm dump %{public}s'", argv_[optind - 1]);
784                 bundleDumpAll = true;
785                 break;
786             }
787             case 'n': {
788                 // 'bm dump -n xxx'
789                 // 'bm dump --bundle-name xxx'
790                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
791                 bundleName = optarg;
792                 bundleDumpInfo = true;
793                 break;
794             }
795             case 's': {
796                 // 'bm dump -n xxx -s'
797                 // 'bm dump --bundle-name xxx --shortcut-info'
798                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
799                 bundleDumpShortcut = true;
800                 break;
801             }
802             case 'u': {
803                 // 'bm dump -n <bundleName> -u userId'
804                 // 'bm dump --bundle-name <bundleName> --user-id userId'
805                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
806                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
807                     APP_LOGE("bm dump with error userId %{private}s", optarg);
808                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
809                     return OHOS::ERR_INVALID_VALUE;
810                 }
811                 break;
812             }
813             case 'd': {
814                 // 'bm dump -n <bundleName> -d deviceId'
815                 // 'bm dump --bundle-name <bundleName> --device-id deviceId'
816                 APP_LOGD("'bm dump %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
817                 deviceId = optarg;
818                 bundleDumpDistributedBundleInfo = true;
819                 break;
820             }
821             default: {
822                 result = OHOS::ERR_INVALID_VALUE;
823                 break;
824             }
825         }
826     }
827     if (result == OHOS::ERR_OK) {
828         if ((resultReceiver_ == "") && bundleDumpShortcut && (bundleName.size() == 0)) {
829             // 'bm dump -s ...' with no bundle name option
830             APP_LOGD("'bm dump -s' with no bundle name option.");
831             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
832             result = OHOS::ERR_INVALID_VALUE;
833         }
834         if ((resultReceiver_ == "") && bundleDumpDistributedBundleInfo && (bundleName.size() == 0)) {
835             // 'bm dump d ...' with no bundle name option
836             APP_LOGD("'bm dump -d' with no bundle name option.");
837             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
838             result = OHOS::ERR_INVALID_VALUE;
839         }
840     }
841     if (result != OHOS::ERR_OK) {
842         resultReceiver_.append(HELP_MSG_DUMP);
843     } else {
844         std::string dumpResults = "";
845         APP_LOGD("dumpResults: %{public}s", dumpResults.c_str());
846         if (bundleDumpShortcut) {
847             dumpResults = DumpShortcutInfos(bundleName, userId);
848         } else if (bundleDumpDistributedBundleInfo) {
849             dumpResults = DumpDistributedBundleInfo(deviceId, bundleName);
850         } else if (bundleDumpAll) {
851             dumpResults = DumpBundleList(userId);
852         } else if (bundleDumpInfo) {
853             dumpResults = DumpBundleInfo(bundleName, userId);
854         }
855         if (dumpResults.empty() || (dumpResults == "")) {
856             dumpResults = HELP_MSG_DUMP_FAILED + "\n";
857         }
858         resultReceiver_.append(dumpResults);
859     }
860 
861     return result;
862 }
863 
RunAsCleanCommand()864 ErrCode BundleManagerShellCommand::RunAsCleanCommand()
865 {
866     int32_t result = OHOS::ERR_OK;
867     int32_t counter = 0;
868     int32_t userId = Constants::UNSPECIFIED_USERID;
869     bool cleanCache = false;
870     bool cleanData = false;
871     std::string bundleName = "";
872     while (true) {
873         counter++;
874         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
875         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
876         if (optind < 0 || optind > argc_) {
877             return OHOS::ERR_INVALID_VALUE;
878         }
879         if (option == -1) {
880             if (counter == 1) {
881                 // When scanning the first argument
882                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
883                     // 'bm clean' with no option: bm clean
884                     // 'bm clean' with a wrong argument: bm clean xxx
885                     APP_LOGD("'bm clean' %{public}s", HELP_MSG_NO_OPTION.c_str());
886 
887                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
888                     result = OHOS::ERR_INVALID_VALUE;
889                 }
890             }
891             break;
892         }
893 
894         if (option == '?') {
895             switch (optopt) {
896                 case 'n': {
897                     // 'bm clean -n' with no argument: bm clean -n
898                     // 'bm clean --bundle-name' with no argument: bm clean --bundle-name
899                     APP_LOGD("'bm clean -n' with no argument.");
900                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
901                     result = OHOS::ERR_INVALID_VALUE;
902                     break;
903                 }
904                 case 'u': {
905                     // 'bm clean -u' with no argument: bm clean -u
906                     // 'bm clean --user-id' with no argument: bm clean --user-id
907                     APP_LOGD("'bm clean -u' with no argument.");
908                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
909                     result = OHOS::ERR_INVALID_VALUE;
910                     break;
911                 }
912                 default: {
913                     // 'bm clean' with an unknown option: bm clear -x
914                     // 'bm clean' with an unknown option: bm clear -xxx
915                     std::string unknownOption = "";
916                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
917                     APP_LOGD("'bm clean' with an unknown option.");
918                     resultReceiver_.append(unknownOptionMsg);
919                     result = OHOS::ERR_INVALID_VALUE;
920                     break;
921                 }
922             }
923             break;
924         }
925 
926         switch (option) {
927             case 'h': {
928                 // 'bm clean -h'
929                 // 'bm clean --help'
930                 APP_LOGD("'bm clean %{public}s'", argv_[optind - 1]);
931                 result = OHOS::ERR_INVALID_VALUE;
932                 break;
933             }
934             case 'n': {
935                 // 'bm clean -n xxx'
936                 // 'bm clean --bundle-name xxx'
937                 APP_LOGD("'bm clean %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
938                 bundleName = optarg;
939                 break;
940             }
941             case 'c': {
942                 // 'bm clean -c'
943                 // 'bm clean --cache'
944                 APP_LOGD("'bm clean %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
945                 cleanCache = cleanData ? false : true;
946                 break;
947             }
948             case 'd': {
949                 // 'bm clean -d'
950                 // 'bm clean --data'
951                 APP_LOGD("'bm clean %{public}s '", argv_[optind - OFFSET_REQUIRED_ARGUMENT]);
952                 cleanData = cleanCache ? false : true;
953                 break;
954             }
955             case 'u': {
956                 // 'bm clean -u userId'
957                 // 'bm clean --user-id userId'
958                 APP_LOGD("'bm clean %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
959                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
960                     APP_LOGE("bm clean with error userId %{private}s", optarg);
961                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
962                     return OHOS::ERR_INVALID_VALUE;
963                 }
964                 break;
965             }
966             default: {
967                 result = OHOS::ERR_INVALID_VALUE;
968                 break;
969             }
970         }
971     }
972 
973     if (result == OHOS::ERR_OK) {
974         if (resultReceiver_ == "" && bundleName.size() == 0) {
975             // 'bm clean ...' with no bundle name option
976             APP_LOGD("'bm clean' with no bundle name option.");
977             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
978             result = OHOS::ERR_INVALID_VALUE;
979         }
980         if (!cleanCache && !cleanData) {
981             APP_LOGD("'bm clean' with no '-c' or '-d' option.");
982             resultReceiver_.append(HELP_MSG_NO_DATA_OR_CACHE_OPTION + "\n");
983             result = OHOS::ERR_INVALID_VALUE;
984         }
985     }
986 
987     if (result != OHOS::ERR_OK) {
988         resultReceiver_.append(HELP_MSG_CLEAN);
989     } else {
990         // bm clean -c
991         if (cleanCache) {
992             if (CleanBundleCacheFilesOperation(bundleName, userId)) {
993                 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_OK + "\n";
994             } else {
995                 resultReceiver_ = STRING_CLEAN_CACHE_BUNDLE_NG + "\n";
996             }
997         }
998         // bm clean -d
999         if (cleanData) {
1000             if (CleanBundleDataFilesOperation(bundleName, userId)) {
1001                 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_OK + "\n");
1002             } else {
1003                 resultReceiver_.append(STRING_CLEAN_DATA_BUNDLE_NG + "\n");
1004             }
1005         }
1006     }
1007     return result;
1008 }
1009 
RunAsEnableCommand()1010 ErrCode BundleManagerShellCommand::RunAsEnableCommand()
1011 {
1012     int result = OHOS::ERR_OK;
1013     int counter = 0;
1014     std::string bundleName = "";
1015     std::string abilityName = "";
1016     int32_t userId = Constants::UNSPECIFIED_USERID;
1017     while (true) {
1018         counter++;
1019         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1020         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1021         if (optind < 0 || optind > argc_) {
1022             return OHOS::ERR_INVALID_VALUE;
1023         }
1024 
1025         if (option == -1) {
1026             if (counter == 1) {
1027                 // When scanning the first argument
1028                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1029                     // 'bm enable' with no option: bm enable
1030                     // 'bm enable' with a wrong argument: bm enable xxx
1031                     APP_LOGD("'bm enable' with no option.");
1032                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1033                     result = OHOS::ERR_INVALID_VALUE;
1034                 }
1035             }
1036             break;
1037         }
1038 
1039         if (option == '?') {
1040             switch (optopt) {
1041                 case 'n': {
1042                     // 'bm enable -n' with no argument: bm enable -n
1043                     // 'bm enable --bundle-name' with no argument: bm enable --bundle-name
1044                     APP_LOGD("'bm enable -n' with no argument.");
1045                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1046                     result = OHOS::ERR_INVALID_VALUE;
1047                     break;
1048                 }
1049                 case 'a': {
1050                     // 'bm enable -a' with no argument: bm enable -a
1051                     // 'bm enable --ability-name' with no argument: bm enable --ability-name
1052                     APP_LOGD("'bm enable -a' with no argument.");
1053                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1054                     result = OHOS::ERR_INVALID_VALUE;
1055                     break;
1056                 }
1057                 case 'u': {
1058                     // 'bm enable -u' with no argument: bm enable -u
1059                     // 'bm enable --user-id' with no argument: bm enable --user-id
1060                     APP_LOGD("'bm enable -u' with no argument.");
1061                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1062                     result = OHOS::ERR_INVALID_VALUE;
1063                     break;
1064                 }
1065                 default: {
1066                     // 'bm enable' with an unknown option: bm enable -x
1067                     // 'bm enable' with an unknown option: bm enable -xxx
1068                     std::string unknownOption = "";
1069                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1070                     APP_LOGD("'bm enable' with an unknown option.");
1071                     resultReceiver_.append(unknownOptionMsg);
1072                     result = OHOS::ERR_INVALID_VALUE;
1073                     break;
1074                 }
1075             }
1076             break;
1077         }
1078 
1079         switch (option) {
1080             case 'h': {
1081                 // 'bm enable-h'
1082                 // 'bm enable --help'
1083                 APP_LOGD("'bm enable %{public}s'", argv_[optind - 1]);
1084                 result = OHOS::ERR_INVALID_VALUE;
1085                 break;
1086             }
1087             case 'n': {
1088                 // 'bm enable -n <bundle-name>'
1089                 // 'bm enable --bundle-name <bundle-name>'
1090                 bundleName = optarg;
1091                 break;
1092             }
1093             case 'a': {
1094                 // 'bm enable -a <ability-name>'
1095                 // 'bm enable --ability-name <ability-name>'
1096                 abilityName = optarg;
1097                 break;
1098             }
1099             case 'u': {
1100                 // 'bm enable -u userId'
1101                 // 'bm enable --user-id userId'
1102                 APP_LOGD("'bm enable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1103                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1104                     APP_LOGE("bm enable with error userId %{private}s", optarg);
1105                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1106                     return OHOS::ERR_INVALID_VALUE;
1107                 }
1108                 break;
1109             }
1110             default: {
1111                 result = OHOS::ERR_INVALID_VALUE;
1112                 break;
1113             }
1114         }
1115     }
1116 
1117     if (result == OHOS::ERR_OK) {
1118         if (resultReceiver_ == "" && bundleName.size() == 0) {
1119             // 'bm enable ...' with no bundle name option
1120             APP_LOGD("'bm enable' with no bundle name option.");
1121 
1122             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1123             result = OHOS::ERR_INVALID_VALUE;
1124         }
1125     }
1126 
1127     if (result != OHOS::ERR_OK) {
1128         resultReceiver_.append(HELP_MSG_ENABLE);
1129     } else {
1130         AbilityInfo abilityInfo;
1131         abilityInfo.name = abilityName;
1132         abilityInfo.bundleName = bundleName;
1133         bool enableResult = SetApplicationEnabledOperation(abilityInfo, true, userId);
1134         if (enableResult) {
1135             resultReceiver_ = STRING_ENABLE_BUNDLE_OK + "\n";
1136         } else {
1137             resultReceiver_ = STRING_ENABLE_BUNDLE_NG + "\n";
1138         }
1139     }
1140     return result;
1141 }
1142 
RunAsDisableCommand()1143 ErrCode BundleManagerShellCommand::RunAsDisableCommand()
1144 {
1145     int result = OHOS::ERR_OK;
1146     int counter = 0;
1147     std::string bundleName = "";
1148     std::string abilityName = "";
1149     int32_t userId = Constants::UNSPECIFIED_USERID;
1150     while (true) {
1151         counter++;
1152         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
1153         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1154         if (optind < 0 || optind > argc_) {
1155             return OHOS::ERR_INVALID_VALUE;
1156         }
1157         if (option == -1) {
1158             if (counter == 1) {
1159                 // When scanning the first argument
1160                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1161                     // 'bm disable' with no option: bm disable
1162                     // 'bm disable' with a wrong argument: bm disable xxx
1163                     APP_LOGD("'bm disable' with no option.");
1164                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1165                     result = OHOS::ERR_INVALID_VALUE;
1166                 }
1167             }
1168             break;
1169         }
1170         if (option == '?') {
1171             switch (optopt) {
1172                 case 'n': {
1173                     // 'bm disable -n' with no argument: bm disable -n
1174                     // 'bm disable --bundle-name' with no argument: bm disable --bundle-name
1175                     APP_LOGD("'bm disable' with no argument.");
1176                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1177                     result = OHOS::ERR_INVALID_VALUE;
1178                     break;
1179                 }
1180                 case 'a': {
1181                     // 'bm disable -a' with no argument: bm disable -a
1182                     // 'bm disable --ability-name' with no argument: bm disable --ability-name
1183                     APP_LOGD("'bm disable -a' with no argument.");
1184                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1185                     result = OHOS::ERR_INVALID_VALUE;
1186                     break;
1187                 }
1188                 case 'u': {
1189                     // 'bm disable -u' with no argument: bm disable -u
1190                     // 'bm disable --user-id' with no argument: bm disable --user-id
1191                     APP_LOGD("'bm disable -u' with no argument.");
1192                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1193                     result = OHOS::ERR_INVALID_VALUE;
1194                     break;
1195                 }
1196                 default: {
1197                     // 'bm disable' with an unknown option: bm disable -x
1198                     // 'bm disable' with an unknown option: bm disable -xxx
1199                     std::string unknownOption = "";
1200                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1201                     APP_LOGD("'bm disable' with an unknown option.");
1202                     resultReceiver_.append(unknownOptionMsg);
1203                     result = OHOS::ERR_INVALID_VALUE;
1204                     break;
1205                 }
1206             }
1207             break;
1208         }
1209         switch (option) {
1210             case 'h': {
1211                 // 'bm disable -h'
1212                 // 'bm disable --help'
1213                 APP_LOGD("'bm disable %{public}s'", argv_[optind - 1]);
1214                 result = OHOS::ERR_INVALID_VALUE;
1215                 break;
1216             }
1217             case 'n': {
1218                 // 'bm disable -n <bundle-name>'
1219                 // 'bm disable --bundle-name <bundle-name>'
1220                 bundleName = optarg;
1221                 break;
1222             }
1223             case 'a': {
1224                 // 'bm disable -a <ability-name>'
1225                 // 'bm disable --ability-name <ability-name>'
1226                 abilityName = optarg;
1227                 break;
1228             }
1229             case 'u': {
1230                 // 'bm disable -u userId'
1231                 // 'bm disable --user-id userId'
1232                 APP_LOGD("'bm disable %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1233                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1234                     APP_LOGE("bm disable with error userId %{private}s", optarg);
1235                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1236                     return OHOS::ERR_INVALID_VALUE;
1237                 }
1238                 break;
1239             }
1240             default: {
1241                 result = OHOS::ERR_INVALID_VALUE;
1242                 break;
1243             }
1244         }
1245     }
1246     if (result == OHOS::ERR_OK) {
1247         if (resultReceiver_ == "" && bundleName.size() == 0) {
1248             // 'bm disable ...' with no bundle name option
1249             APP_LOGD("'bm disable' with no bundle name option.");
1250             resultReceiver_.append(HELP_MSG_NO_BUNDLE_NAME_OPTION + "\n");
1251             result = OHOS::ERR_INVALID_VALUE;
1252         }
1253     }
1254     if (result != OHOS::ERR_OK) {
1255         resultReceiver_.append(HELP_MSG_DISABLE);
1256     } else {
1257         AbilityInfo abilityInfo;
1258         abilityInfo.name = abilityName;
1259         abilityInfo.bundleName = bundleName;
1260         bool enableResult = SetApplicationEnabledOperation(abilityInfo, false, userId);
1261         if (enableResult) {
1262             resultReceiver_ = STRING_DISABLE_BUNDLE_OK + "\n";
1263         } else {
1264             resultReceiver_ = STRING_DISABLE_BUNDLE_NG + "\n";
1265         }
1266     }
1267     return result;
1268 }
1269 
RunAsGetCommand()1270 ErrCode BundleManagerShellCommand::RunAsGetCommand()
1271 {
1272     int result = OHOS::ERR_OK;
1273     int counter = 0;
1274     while (true) {
1275         counter++;
1276         if (argc_ > MAX_ARGUEMENTS_NUMBER) {
1277             resultReceiver_.append(HELP_MSG_GET);
1278             return OHOS::ERR_INVALID_VALUE;
1279         }
1280         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_GET.c_str(), LONG_OPTIONS_GET, nullptr);
1281         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1282         if (optind < 0 || optind > argc_) {
1283             return OHOS::ERR_INVALID_VALUE;
1284         }
1285         if (option == -1) {
1286             if (counter == 1) {
1287                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1288                     // 1.'bm get' with no option: bm get
1289                     // 2.'bm get' with a wrong argument: bm get -xxx
1290                     APP_LOGD("'bm get' %{public}s", HELP_MSG_NO_OPTION.c_str());
1291                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1292                     result = OHOS::ERR_INVALID_VALUE;
1293                 }
1294             }
1295             break;
1296         }
1297         switch (option) {
1298             case 'h': {
1299                 result = OHOS::ERR_INVALID_VALUE;
1300                 break;
1301             }
1302             case 'u': {
1303                 break;
1304             }
1305             default: {
1306                 result = OHOS::ERR_INVALID_VALUE;
1307                 resultReceiver_.append(STRING_INCORRECT_OPTION + "\n");
1308                 break;
1309             }
1310         }
1311     }
1312     if (result != OHOS::ERR_OK) {
1313         resultReceiver_.append(HELP_MSG_GET);
1314         return result;
1315     }
1316     resultReceiver_.append(STRING_GET_UDID_OK + "\n");
1317     resultReceiver_.append(GetUdid() + "\n");
1318     return result;
1319 }
1320 
RunAsQuickFixCommand()1321 ErrCode BundleManagerShellCommand::RunAsQuickFixCommand()
1322 {
1323     for (auto index = INDEX_OFFSET; index < argc_; ++index) {
1324         APP_LOGD("argv_[%{public}d]: %{public}s", index, argv_[index]);
1325         std::string opt = argv_[index];
1326         if ((opt == "-h") || (opt == "--help")) {
1327             resultReceiver_.append(HELP_MSG_QUICK_FIX);
1328             return ERR_OK;
1329         } else if ((opt == "-a") || (opt == "--apply")) {
1330             if (index >= argc_ - INDEX_OFFSET) {
1331                 resultReceiver_.append("error: option [--apply] is incorrect.\n");
1332                 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1333                 return ERR_INVALID_VALUE;
1334             }
1335 
1336             std::string argKey = argv_[++index];
1337             index++;
1338             if (argKey == "-f" || argKey == "--file-path") {
1339                 std::vector<std::string> quickFixFiles;
1340                 // collect value of multi file-path.
1341                 for (; index < argc_ && index >= INDEX_OFFSET; ++index) {
1342                     if (argList_[index - INDEX_OFFSET] == "-q" || argList_[index - INDEX_OFFSET] == "--query" ||
1343                         argList_[index - INDEX_OFFSET] == "-b" || argList_[index - INDEX_OFFSET] == "--bundle-name" ||
1344                         argList_[index - INDEX_OFFSET] == "-a" || argList_[index - INDEX_OFFSET] == "--apply" ||
1345                         argList_[index - INDEX_OFFSET] == "-f" || argList_[index - INDEX_OFFSET] == "--file-path") {
1346                         break;
1347                     }
1348                     quickFixFiles.emplace_back(argList_[index - INDEX_OFFSET]);
1349                 }
1350 
1351                 return QuickFixCommand::ApplyQuickFix(quickFixFiles, resultReceiver_);
1352             }
1353         } else if ((opt == "-q") || (opt == "--query")) {
1354             if (index >= argc_ - INDEX_OFFSET) {
1355                 resultReceiver_.append("error: option [--query] is incorrect.\n");
1356                 resultReceiver_.append(HELP_MSG_QUICK_FIX);
1357                 return ERR_INVALID_VALUE;
1358             }
1359 
1360             std::string bundleName;
1361             std::string argKey = argv_[++index];
1362             std::string argValue = argv_[++index];
1363             if (argKey == "-b" || argKey == "--bundle-name") {
1364                 bundleName = argValue;
1365             }
1366 
1367             return QuickFixCommand::GetApplyedQuickFixInfo(bundleName, resultReceiver_);
1368         } else {
1369             resultReceiver_.append("error: unknown option.\n");
1370             resultReceiver_.append(HELP_MSG_QUICK_FIX);
1371             return ERR_INVALID_VALUE;
1372         }
1373     }
1374 
1375     resultReceiver_.append("error: parameter is not enough.\n");
1376     resultReceiver_.append(HELP_MSG_QUICK_FIX);
1377     return ERR_INVALID_VALUE;
1378 }
1379 
RunAsDumpOverlay()1380 ErrCode BundleManagerShellCommand::RunAsDumpOverlay()
1381 {
1382     int result = OHOS::ERR_OK;
1383     int counter = 0;
1384     int32_t userId = Constants::UNSPECIFIED_USERID;
1385     std::string bundleName = "";
1386     std::string moduleName = "";
1387     std::string targetModuleName = "";
1388     while (true) {
1389         counter++;
1390         if (argc_ > MAX_OVERLAY_ARGUEMENTS_NUMBER) {
1391             resultReceiver_.append(HELP_MSG_OVERLAY);
1392             return OHOS::ERR_INVALID_VALUE;
1393         }
1394         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_OVERLAY.c_str(), LONG_OPTIONS_OVERLAY,
1395             nullptr);
1396         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1397         if (optind < 0 || optind > argc_) {
1398             return OHOS::ERR_INVALID_VALUE;
1399         }
1400         if (option == -1) {
1401             if (counter == 1) {
1402                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1403                     // 1.'bm dump-overlay' with no option: bm dump-overlay
1404                     // 2.'bm dump-overlay' with a wrong argument: bm dump-overlay -xxx
1405                     APP_LOGD("'bm dump-overlay' %{public}s", HELP_MSG_NO_OPTION.c_str());
1406                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1407                     result = OHOS::ERR_INVALID_VALUE;
1408                 }
1409             }
1410             break;
1411         }
1412         if (option == '?') {
1413             switch (optopt) {
1414                 case 'b': {
1415                     // 'bm dump-overlay -b' with no argument
1416                     // 'bm dump-overlay --bundle-name' with no argument
1417                     APP_LOGD("'bm dump-overlay -b' with no argument.");
1418                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1419                     result = OHOS::ERR_INVALID_VALUE;
1420                     break;
1421                 }
1422                 case 'm': {
1423                     // 'bm dump-overlay -m' with no argument: bm enable -m
1424                     // 'bm dump-overlay --bundle-name' with no argument: bm dump-overlay --bundle-name
1425                     APP_LOGD("'bm dump-overlay -m' with no argument.");
1426                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1427                     result = OHOS::ERR_INVALID_VALUE;
1428                     break;
1429                 }
1430                 case 't': {
1431                     // 'bm dump-overlay -t' with no argument
1432                     // 'bm dump-overlay --target-module-name' with no argument
1433                     APP_LOGD("'bm dump-overlay -t' with no argument.");
1434                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1435                     result = OHOS::ERR_INVALID_VALUE;
1436                     break;
1437                 }
1438                 case 'u': {
1439                     // 'bm dump-overlay -u' with no argument: bm dump-overlay -u
1440                     // 'bm dump-overlay --user-id' with no argument: bm dump-overlay --user-id
1441                     APP_LOGD("'bm dump-overlay -u' with no argument.");
1442                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1443                     result = OHOS::ERR_INVALID_VALUE;
1444                     break;
1445                 }
1446                 default: {
1447                     // 'bm dump-overlay' with an unknown option
1448                     // 'bm dump-overlay' with an unknown option
1449                     std::string unknownOption = "";
1450                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1451                     APP_LOGD("'bm dump-overlay' with an unknown option.");
1452                     resultReceiver_.append(unknownOptionMsg);
1453                     result = OHOS::ERR_INVALID_VALUE;
1454                     break;
1455                 }
1456             }
1457             break;
1458         }
1459 
1460         switch (option) {
1461             case 'h': {
1462                 // 'bm dump-overlay -h'
1463                 // 'bm dump-overlay --help'
1464                 APP_LOGD("'bm dump-overlay %{public}s'", argv_[optind - 1]);
1465                 result = OHOS::ERR_INVALID_VALUE;
1466                 break;
1467             }
1468             case 'b': {
1469                 // 'bm dump-overlay -b <bundle-name>'
1470                 // 'bm dump-overlay --bundle-name <bundle-name>'
1471                 bundleName = optarg;
1472                 break;
1473             }
1474             case 'm': {
1475                 // 'bm dump-overlay -m <module-name>'
1476                 // 'bm dump-overlay --module-name <module-name>'
1477                 moduleName = optarg;
1478                 break;
1479             }
1480             case 't': {
1481                 // 'bm dump-overlay -t <target-module-name>'
1482                 // 'bm dump-overlay --target-module-name <target-module-name>'
1483                 targetModuleName = optarg;
1484                 break;
1485             }
1486             case 'u': {
1487                 APP_LOGD("'bm dump-overlay %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT], optarg);
1488                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1489                     APP_LOGE("bm dump-overlay with error userId %{private}s", optarg);
1490                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1491                     return OHOS::ERR_INVALID_VALUE;
1492                 }
1493                 break;
1494             }
1495             default: {
1496                 result = OHOS::ERR_INVALID_VALUE;
1497                 break;
1498             }
1499         }
1500     }
1501     if (result != OHOS::ERR_OK) {
1502         resultReceiver_.append(HELP_MSG_OVERLAY);
1503         return result;
1504     }
1505 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
1506     auto res = DumpOverlayInfo(bundleName, moduleName, targetModuleName, userId);
1507     if (res.empty()) {
1508         resultReceiver_.append(STRING_DUMP_OVERLAY_NG + "\n");
1509     } else {
1510         resultReceiver_.append(STRING_DUMP_OVERLAY_OK + "\n");
1511         resultReceiver_.append(res + "\n");
1512     }
1513 #else
1514     resultReceiver_.append(MSG_ERR_BUNDLEMANAGER_OVERLAY_FEATURE_IS_NOT_SUPPORTED);
1515 #endif
1516     return result;
1517 }
1518 
RunAsDumpTargetOverlay()1519 ErrCode BundleManagerShellCommand::RunAsDumpTargetOverlay()
1520 {
1521     int result = OHOS::ERR_OK;
1522     int counter = 0;
1523     int32_t userId = Constants::UNSPECIFIED_USERID;
1524     std::string bundleName = "";
1525     std::string moduleName = "";
1526     while (true) {
1527         counter++;
1528         if (argc_ > MAX_OVERLAY_ARGUEMENTS_NUMBER) {
1529             resultReceiver_.append(HELP_MSG_OVERLAY_TARGET);
1530             return OHOS::ERR_INVALID_VALUE;
1531         }
1532         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_OVERLAY_TARGET.c_str(), LONG_OPTIONS_OVERLAY_TARGET,
1533             nullptr);
1534         APP_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
1535         if (optind < 0 || optind > argc_) {
1536             return OHOS::ERR_INVALID_VALUE;
1537         }
1538         if (option == -1) {
1539             if (counter == 1) {
1540                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
1541                     // 1.'bm dump-target-overlay' with no option: bm dump-target-overlay
1542                     // 2.'bm dump-target-overlay' with a wrong argument: bm dump-target-overlay -xxx
1543                     APP_LOGD("'bm dump-target-overlay' %{public}s", HELP_MSG_NO_OPTION.c_str());
1544                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
1545                     result = OHOS::ERR_INVALID_VALUE;
1546                 }
1547             }
1548             break;
1549         }
1550         if (option == '?') {
1551             switch (optopt) {
1552                 case 'b': {
1553                     // 'bm dump-target-overlay -b' with no argument
1554                     // 'bm dump-target-overlay --bundle-name' with no argument
1555                     APP_LOGD("'bm dump-target-overlay -b' with no argument.");
1556                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1557                     result = OHOS::ERR_INVALID_VALUE;
1558                     break;
1559                 }
1560                 case 'm': {
1561                     // 'bm dump-target-overlay -m' with no argument: bm enable -m
1562                     // 'bm dump-target-overlay --bundle-name' with no argument: bm dump-target-overlay --bundle-name
1563                     APP_LOGD("'bm dump-target-overlay -m' with no argument.");
1564                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1565                     result = OHOS::ERR_INVALID_VALUE;
1566                     break;
1567                 }
1568                 case 'u': {
1569                     // 'bm dump-target-overlay -u' with no argument: bm dump-target-overlay -u
1570                     // 'bm dump-target-overlay --user-id' with no argument: bm  dump-target-overlay --user-id
1571                     APP_LOGD("'bm dump-target-overlay -u' with no argument.");
1572                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1573                     result = OHOS::ERR_INVALID_VALUE;
1574                     break;
1575                 }
1576                 default: {
1577                     // 'bm dump-target-overlay' with an unknown option
1578                     // 'bm dump-target-overlay' with an unknown option
1579                     std::string unknownOption = "";
1580                     std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
1581                     APP_LOGD("'bm dump-target-overlay' with an unknown option.");
1582                     resultReceiver_.append(unknownOptionMsg);
1583                     result = OHOS::ERR_INVALID_VALUE;
1584                     break;
1585                 }
1586             }
1587             break;
1588         }
1589 
1590         switch (option) {
1591             case 'h': {
1592                 // 'bm dump-target-overlay -h'
1593                 // 'bm dump-target-overlay --help'
1594                 APP_LOGD("'bm dump-target-overlay %{public}s'", argv_[optind - 1]);
1595                 result = OHOS::ERR_INVALID_VALUE;
1596                 break;
1597             }
1598             case 'b': {
1599                 // 'bm dump-target-overlay -b <bundle-name>'
1600                 // 'bm dump-target-overlay --bundle-name <bundle-name>'
1601                 bundleName = optarg;
1602                 break;
1603             }
1604             case 'm': {
1605                 // 'bm dump-target-overlay -m <module-name>'
1606                 // 'bm dump-target-overlay --module-name <module-name>'
1607                 moduleName = optarg;
1608                 break;
1609             }
1610             case 'u': {
1611                 APP_LOGD("'bm dump-target-overlay %{public}s %{public}s'", argv_[optind - OFFSET_REQUIRED_ARGUMENT],
1612                     optarg);
1613                 if (!OHOS::StrToInt(optarg, userId) || userId < 0) {
1614                     APP_LOGE("bm dump-target-overlay with error userId %{private}s", optarg);
1615                     resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
1616                     return OHOS::ERR_INVALID_VALUE;
1617                 }
1618                 break;
1619             }
1620             default: {
1621                 result = OHOS::ERR_INVALID_VALUE;
1622                 break;
1623             }
1624         }
1625     }
1626     if (result != OHOS::ERR_OK) {
1627         resultReceiver_.append(HELP_MSG_OVERLAY_TARGET);
1628         return result;
1629     }
1630 #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION
1631     auto res = DumpTargetOverlayInfo(bundleName, moduleName, userId);
1632     if (res.empty()) {
1633         resultReceiver_.append(STRING_DUMP_TARGET_OVERLAY_NG + "\n");
1634     } else {
1635         resultReceiver_.append(STRING_DUMP_TARGET_OVERLAY_OK + "\n");
1636         resultReceiver_.append(res + "\n");
1637     }
1638 #else
1639     resultReceiver_.append(MSG_ERR_BUNDLEMANAGER_OVERLAY_FEATURE_IS_NOT_SUPPORTED);
1640 #endif
1641     return result;
1642 }
1643 
1644 
GetUdid() const1645 std::string BundleManagerShellCommand::GetUdid() const
1646 {
1647     char innerUdid[DEVICE_UDID_LENGTH] = { 0 };
1648     int ret = GetDevUdid(innerUdid, DEVICE_UDID_LENGTH);
1649     if (ret != 0) {
1650         APP_LOGE("GetUdid failed! ret = %{public}d.", ret);
1651         return STRING_GET_UDID_NG;
1652     }
1653     std::string udid = innerUdid;
1654     return udid;
1655 }
1656 
DumpBundleList(int32_t userId) const1657 std::string BundleManagerShellCommand::DumpBundleList(int32_t userId) const
1658 {
1659     std::string dumpResults;
1660     bool dumpRet = bundleMgrProxy_->DumpInfos(
1661         DumpFlag::DUMP_BUNDLE_LIST, BUNDLE_NAME_EMPTY, userId, dumpResults);
1662     if (!dumpRet) {
1663         APP_LOGE("failed to dump bundle list.");
1664     }
1665     return dumpResults;
1666 }
1667 
DumpBundleInfo(const std::string & bundleName,int32_t userId) const1668 std::string BundleManagerShellCommand::DumpBundleInfo(const std::string &bundleName, int32_t userId) const
1669 {
1670     std::string dumpResults;
1671     bool dumpRet = bundleMgrProxy_->DumpInfos(
1672         DumpFlag::DUMP_BUNDLE_INFO, bundleName, userId, dumpResults);
1673     if (!dumpRet) {
1674         APP_LOGE("failed to dump bundle info.");
1675     }
1676     return dumpResults;
1677 }
1678 
DumpShortcutInfos(const std::string & bundleName,int32_t userId) const1679 std::string BundleManagerShellCommand::DumpShortcutInfos(const std::string &bundleName, int32_t userId) const
1680 {
1681     std::string dumpResults;
1682     bool dumpRet = bundleMgrProxy_->DumpInfos(
1683         DumpFlag::DUMP_SHORTCUT_INFO, bundleName, userId, dumpResults);
1684     if (!dumpRet) {
1685         APP_LOGE("failed to dump shortcut infos.");
1686     }
1687     return dumpResults;
1688 }
1689 
DumpDistributedBundleInfo(const std::string & deviceId,const std::string & bundleName)1690 std::string BundleManagerShellCommand::DumpDistributedBundleInfo(
1691     const std::string &deviceId, const std::string &bundleName)
1692 {
1693     std::string dumpResults = "";
1694     DistributedBundleInfo distributedBundleInfo;
1695     bool dumpRet = bundleMgrProxy_->GetDistributedBundleInfo(deviceId, bundleName, distributedBundleInfo);
1696     if (!dumpRet) {
1697         APP_LOGE("failed to dump distributed bundleInfo.");
1698     } else {
1699         dumpResults.append("distributed bundleInfo");
1700         dumpResults.append(":\n");
1701         dumpResults.append(distributedBundleInfo.ToString());
1702         dumpResults.append("\n");
1703     }
1704     return dumpResults;
1705 }
1706 
DumpDependentModuleNames(const std::string & bundleName,const std::string & moduleName) const1707 std::string BundleManagerShellCommand::DumpDependentModuleNames(
1708     const std::string &bundleName,
1709     const std::string &moduleName) const
1710 {
1711     APP_LOGD("DumpDependentModuleNames bundleName: %{public}s, moduleName: %{public}s",
1712         bundleName.c_str(), moduleName.c_str());
1713     std::string dumpResults = "";
1714     std::vector<std::string> dependentModuleNames;
1715     bool dumpRet = bundleMgrProxy_->GetAllDependentModuleNames(bundleName, moduleName, dependentModuleNames);
1716     if (!dumpRet) {
1717         APP_LOGE("failed to dump dependent module name.");
1718     } else {
1719         dumpResults.append("dependent moduleNames:");
1720         for (const auto &name : dependentModuleNames) {
1721             dumpResults.append("\n");
1722             dumpResults.append(name);
1723         }
1724         dumpResults.append("\n");
1725     }
1726     return dumpResults;
1727 }
1728 
GetAbsPaths(const std::vector<std::string> & paths,std::vector<std::string> & absPaths) const1729 void BundleManagerShellCommand::GetAbsPaths(
1730     const std::vector<std::string> &paths, std::vector<std::string> &absPaths) const
1731 {
1732     std::vector<std::string> realPathVec;
1733     for (auto &bundlePath : paths) {
1734         std::string absoluteBundlePath = "";
1735         if (bundlePath.empty()) {
1736             continue;
1737         }
1738         if (bundlePath.at(0) == '/') {
1739             // absolute path
1740             absoluteBundlePath.append(bundlePath);
1741         } else {
1742             // relative path
1743             char *currentPathPtr = getcwd(nullptr, 0);
1744 
1745             if (currentPathPtr != nullptr) {
1746                 absoluteBundlePath.append(currentPathPtr);
1747                 absoluteBundlePath.append('/' + bundlePath);
1748 
1749                 free(currentPathPtr);
1750                 currentPathPtr = nullptr;
1751             }
1752         }
1753         realPathVec.emplace_back(absoluteBundlePath);
1754     }
1755 
1756     for (const auto &path : realPathVec) {
1757         if (std::find(absPaths.begin(), absPaths.end(), path) == absPaths.end()) {
1758             absPaths.emplace_back(path);
1759         }
1760     }
1761 }
1762 
InstallOperation(const std::vector<std::string> & bundlePaths,InstallParam & installParam,int32_t waittingTime) const1763 int32_t BundleManagerShellCommand::InstallOperation(const std::vector<std::string> &bundlePaths,
1764     InstallParam &installParam, int32_t waittingTime) const
1765 {
1766     std::vector<std::string> pathVec;
1767     GetAbsPaths(bundlePaths, pathVec);
1768 
1769     std::vector<std::string> hspPathVec;
1770     GetAbsPaths(installParam.sharedBundleDirPaths, hspPathVec);
1771     installParam.sharedBundleDirPaths = hspPathVec;
1772 
1773     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl(waittingTime));
1774     if (statusReceiver == nullptr) {
1775         APP_LOGE("statusReceiver is null");
1776         return IStatusReceiver::ERR_UNKNOWN;
1777     }
1778     sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1779     if (recipient == nullptr) {
1780         APP_LOGE("recipient is null");
1781         return IStatusReceiver::ERR_UNKNOWN;
1782     }
1783     bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1784     ErrCode res = bundleInstallerProxy_->StreamInstall(pathVec, installParam, statusReceiver);
1785     APP_LOGD("StreamInstall result is %{public}d", res);
1786     if (res == ERR_OK) {
1787         return statusReceiver->GetResultCode();
1788     }
1789     if (res == ERR_APPEXECFWK_INSTALL_PARAM_ERROR) {
1790         APP_LOGE("install param error");
1791         return IStatusReceiver::ERR_INSTALL_PARAM_ERROR;
1792     }
1793     if (res == ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR) {
1794         APP_LOGE("install internal error");
1795         return IStatusReceiver::ERR_INSTALL_INTERNAL_ERROR;
1796     }
1797     if (res == ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID) {
1798         APP_LOGE("install invalid path");
1799         return IStatusReceiver::ERR_INSTALL_FILE_PATH_INVALID;
1800     }
1801     if (res == ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT) {
1802         APP_LOGE("install failed due to no space left");
1803         return IStatusReceiver::ERR_INSTALL_DISK_MEM_INSUFFICIENT;
1804     }
1805     if (res == ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FILE_IS_INVALID) {
1806         APP_LOGE("install failed due to code signature file is invalid");
1807         return IStatusReceiver::ERR_INSTALL_CODE_SIGNATURE_FILE_IS_INVALID;
1808     }
1809 
1810     return res;
1811 }
1812 
UninstallOperation(const std::string & bundleName,const std::string & moduleName,InstallParam & installParam) const1813 int32_t BundleManagerShellCommand::UninstallOperation(
1814     const std::string &bundleName, const std::string &moduleName, InstallParam &installParam) const
1815 {
1816     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
1817     if (statusReceiver == nullptr) {
1818         APP_LOGE("statusReceiver is null");
1819         return IStatusReceiver::ERR_UNKNOWN;
1820     }
1821 
1822     APP_LOGD("bundleName: %{public}s", bundleName.c_str());
1823     APP_LOGD("moduleName: %{public}s", moduleName.c_str());
1824 
1825     sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1826     if (recipient == nullptr) {
1827         APP_LOGE("recipient is null");
1828         return IStatusReceiver::ERR_UNKNOWN;
1829     }
1830     bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1831     if (moduleName.size() != 0) {
1832         bundleInstallerProxy_->Uninstall(bundleName, moduleName, installParam, statusReceiver);
1833     } else {
1834         bundleInstallerProxy_->Uninstall(bundleName, installParam, statusReceiver);
1835     }
1836 
1837     return statusReceiver->GetResultCode();
1838 }
1839 
UninstallSharedOperation(const UninstallParam & uninstallParam) const1840 int32_t BundleManagerShellCommand::UninstallSharedOperation(const UninstallParam &uninstallParam) const
1841 {
1842     sptr<StatusReceiverImpl> statusReceiver(new (std::nothrow) StatusReceiverImpl());
1843     if (statusReceiver == nullptr) {
1844         APP_LOGE("statusReceiver is null");
1845         return IStatusReceiver::ERR_UNKNOWN;
1846     }
1847 
1848     sptr<BundleDeathRecipient> recipient(new (std::nothrow) BundleDeathRecipient(statusReceiver));
1849     if (recipient == nullptr) {
1850         APP_LOGE("recipient is null");
1851         return IStatusReceiver::ERR_UNKNOWN;
1852     }
1853     bundleInstallerProxy_->AsObject()->AddDeathRecipient(recipient);
1854 
1855     bundleInstallerProxy_->Uninstall(uninstallParam, statusReceiver);
1856     return statusReceiver->GetResultCode();
1857 }
1858 
CleanBundleCacheFilesOperation(const std::string & bundleName,int32_t userId) const1859 bool BundleManagerShellCommand::CleanBundleCacheFilesOperation(const std::string &bundleName, int32_t userId) const
1860 {
1861     userId = BundleCommandCommon::GetCurrentUserId(userId);
1862     sptr<CleanCacheCallbackImpl> cleanCacheCallBack(new (std::nothrow) CleanCacheCallbackImpl());
1863     if (cleanCacheCallBack == nullptr) {
1864         APP_LOGE("cleanCacheCallBack is null");
1865         return false;
1866     }
1867     ErrCode cleanRet = bundleMgrProxy_->CleanBundleCacheFiles(bundleName, cleanCacheCallBack, userId);
1868     if (cleanRet == ERR_OK) {
1869         return cleanCacheCallBack->GetResultCode();
1870     }
1871     APP_LOGE("clean bundle cache files operation failed");
1872     return false;
1873 }
1874 
CleanBundleDataFilesOperation(const std::string & bundleName,int32_t userId) const1875 bool BundleManagerShellCommand::CleanBundleDataFilesOperation(const std::string &bundleName, int32_t userId) const
1876 {
1877     APP_LOGD("bundleName: %{public}s, userId:%{public}d", bundleName.c_str(), userId);
1878     userId = BundleCommandCommon::GetCurrentUserId(userId);
1879     bool cleanRet = bundleMgrProxy_->CleanBundleDataFiles(bundleName, userId);
1880     if (!cleanRet) {
1881         APP_LOGE("clean bundle data files operation failed");
1882     }
1883     return cleanRet;
1884 }
1885 
SetApplicationEnabledOperation(const AbilityInfo & abilityInfo,bool isEnable,int32_t userId) const1886 bool BundleManagerShellCommand::SetApplicationEnabledOperation(const AbilityInfo &abilityInfo,
1887     bool isEnable, int32_t userId) const
1888 {
1889     APP_LOGD("bundleName: %{public}s", abilityInfo.bundleName.c_str());
1890     userId = BundleCommandCommon::GetCurrentUserId(userId);
1891     int32_t ret;
1892     if (abilityInfo.name.size() == 0) {
1893         ret = bundleMgrProxy_->SetApplicationEnabled(abilityInfo.bundleName, isEnable, userId);
1894     } else {
1895         ret = bundleMgrProxy_->SetAbilityEnabled(abilityInfo, isEnable, userId);
1896     }
1897     if (ret != 0) {
1898         if (isEnable) {
1899             APP_LOGE("enable bundle failed");
1900         } else {
1901             APP_LOGE("disable bundle failed");
1902         }
1903         return false;
1904     }
1905     return true;
1906 }
1907 
DumpOverlayInfo(const std::string & bundleName,const std::string & moduleName,const std::string & targetModuleName,int32_t userId)1908 std::string BundleManagerShellCommand::DumpOverlayInfo(const std::string &bundleName, const std::string &moduleName,
1909     const std::string &targetModuleName, int32_t userId)
1910 {
1911     std::string res = "";
1912     if ((bundleName.empty()) || (!moduleName.empty() && !targetModuleName.empty())) {
1913         APP_LOGE("error value of the dump-overlay command options");
1914         return res;
1915     }
1916 
1917     auto overlayManagerProxy = bundleMgrProxy_->GetOverlayManagerProxy();
1918     if (overlayManagerProxy == nullptr) {
1919         APP_LOGE("overlayManagerProxy is null");
1920         return res;
1921     }
1922     std::vector<OverlayModuleInfo> overlayModuleInfos;
1923     OverlayModuleInfo overlayModuleInfo;
1924     ErrCode ret = ERR_OK;
1925     userId = BundleCommandCommon::GetCurrentUserId(userId);
1926     if (moduleName.empty() && targetModuleName.empty()) {
1927         ret = overlayManagerProxy->GetAllOverlayModuleInfo(bundleName, overlayModuleInfos, userId);
1928         if (overlayModuleInfos.empty()) {
1929             ret = ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NO_OVERLAY_MODULE_INFO;
1930         }
1931     } else if (!moduleName.empty()) {
1932         ret = overlayManagerProxy->GetOverlayModuleInfo(bundleName, moduleName, overlayModuleInfo, userId);
1933     } else {
1934         ret = overlayManagerProxy->GetOverlayModuleInfoForTarget(bundleName, targetModuleName, overlayModuleInfos,
1935             userId);
1936         if (overlayModuleInfos.empty()) {
1937             ret = ERR_BUNDLEMANAGER_OVERLAY_QUERY_FAILED_NO_OVERLAY_MODULE_INFO;
1938         }
1939     }
1940     if (ret != ERR_OK) {
1941         APP_LOGE("dump-overlay failed due to errcode %{public}d", ret);
1942         return res;
1943     }
1944 
1945     nlohmann::json overlayInfoJson;
1946     if (!overlayModuleInfos.empty()) {
1947         overlayInfoJson = nlohmann::json {{OVERLAY_MODULE_INFOS, overlayModuleInfos}};
1948     } else {
1949         overlayInfoJson = nlohmann::json {{OVERLAY_MODULE_INFO, overlayModuleInfo}};
1950     }
1951     return overlayInfoJson.dump(Constants::DUMP_INDENT);
1952 }
1953 
DumpTargetOverlayInfo(const std::string & bundleName,const std::string & moduleName,int32_t userId)1954 std::string BundleManagerShellCommand::DumpTargetOverlayInfo(const std::string &bundleName,
1955     const std::string &moduleName, int32_t userId)
1956 {
1957     std::string res = "";
1958     if (bundleName.empty()) {
1959         APP_LOGE("error value of the dump-target-overlay command options");
1960         return res;
1961     }
1962     auto overlayManagerProxy = bundleMgrProxy_->GetOverlayManagerProxy();
1963     if (overlayManagerProxy == nullptr) {
1964         APP_LOGE("overlayManagerProxy is null");
1965         return res;
1966     }
1967 
1968     userId = BundleCommandCommon::GetCurrentUserId(userId);
1969     ErrCode ret = ERR_OK;
1970     nlohmann::json overlayInfoJson;
1971     if (moduleName.empty()) {
1972         std::vector<OverlayBundleInfo> overlayBundleInfos;
1973         ret = overlayManagerProxy->GetOverlayBundleInfoForTarget(bundleName, overlayBundleInfos, userId);
1974         if (ret != ERR_OK || overlayBundleInfos.empty()) {
1975             APP_LOGE("dump-target-overlay failed due to errcode %{public}d", ret);
1976             return res;
1977         }
1978         overlayInfoJson = nlohmann::json {{OVERLAY_BUNDLE_INFOS, overlayBundleInfos}};
1979     } else {
1980         std::vector<OverlayModuleInfo> overlayModuleInfos;
1981         ret = overlayManagerProxy->GetOverlayModuleInfoForTarget(bundleName, moduleName, overlayModuleInfos, userId);
1982         if (ret != ERR_OK || overlayModuleInfos.empty()) {
1983             APP_LOGE("dump-target-overlay failed due to errcode %{public}d", ret);
1984             return res;
1985         }
1986         overlayInfoJson = nlohmann::json {{OVERLAY_MODULE_INFOS, overlayModuleInfos}};
1987     }
1988     return overlayInfoJson.dump(Constants::DUMP_INDENT);
1989 }
1990 
RunAsDumpSharedDependenciesCommand()1991 ErrCode BundleManagerShellCommand::RunAsDumpSharedDependenciesCommand()
1992 {
1993     int32_t result = OHOS::ERR_OK;
1994     int32_t counter = 0;
1995     std::string bundleName;
1996     std::string moduleName;
1997     while (true) {
1998         counter++;
1999         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP_SHARED_DEPENDENCIES.c_str(),
2000             LONG_OPTIONS_DUMP_SHARED_DEPENDENCIES, nullptr);
2001         if (optind < 0 || optind > argc_) {
2002             return OHOS::ERR_INVALID_VALUE;
2003         }
2004         if (option == -1) {
2005             if (counter == 1) {
2006                 // When scanning the first argument
2007                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
2008                     // 'bm dump-dependencies' with no option: bm dump-dependencies
2009                     // 'bm dump-dependencies' with a wrong argument: bm dump-dependencies xxx
2010                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
2011                     result = OHOS::ERR_INVALID_VALUE;
2012                 }
2013             }
2014             break;
2015         }
2016         result = ParseSharedDependenciesCommand(option, bundleName, moduleName);
2017         if (option == '?') {
2018             break;
2019         }
2020     }
2021     if (result == OHOS::ERR_OK) {
2022         if ((resultReceiver_ == "") && (bundleName.size() == 0 || moduleName.size() == 0)) {
2023             // 'bm dump-dependencies -n -m ...' with no bundle name option
2024             resultReceiver_.append(HELP_MSG_NO_REMOVABLE_OPTION);
2025             result = OHOS::ERR_INVALID_VALUE;
2026         }
2027     }
2028     if (result != OHOS::ERR_OK) {
2029         resultReceiver_.append(HELP_MSG_DUMP_SHARED_DEPENDENCIES);
2030     } else {
2031         std::string dumpResults = DumpSharedDependencies(bundleName, moduleName);
2032         if (dumpResults.empty() || (dumpResults == "")) {
2033             dumpResults = HELP_MSG_DUMP_FAILED + "\n";
2034         }
2035         resultReceiver_.append(dumpResults);
2036     }
2037     return result;
2038 }
2039 
ParseSharedDependenciesCommand(int32_t option,std::string & bundleName,std::string & moduleName)2040 ErrCode BundleManagerShellCommand::ParseSharedDependenciesCommand(int32_t option, std::string &bundleName,
2041     std::string &moduleName)
2042 {
2043     int32_t result = OHOS::ERR_OK;
2044     if (option == '?') {
2045         switch (optopt) {
2046             case 'n': {
2047                 // 'bm dump-dependencies -n' with no argument: bm dump-dependencies -n
2048                 // 'bm dump-dependencies --bundle-name' with no argument: bm dump-dependencies --bundle-name
2049                 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
2050                 result = OHOS::ERR_INVALID_VALUE;
2051                 break;
2052             }
2053             case 'm': {
2054                 // 'bm dump-dependencies -m' with no argument: bm dump-dependencies -m
2055                 // 'bm dump-dependencies --module-name' with no argument: bm dump-dependencies --module-name
2056                 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
2057                 result = OHOS::ERR_INVALID_VALUE;
2058                 break;
2059             }
2060             default: {
2061                 // 'bm dump-dependencies' with an unknown option: bm dump-dependencies -x
2062                 // 'bm dump-dependencies' with an unknown option: bm dump-dependencies -xxx
2063                 std::string unknownOption = "";
2064                 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
2065                 resultReceiver_.append(unknownOptionMsg);
2066                 result = OHOS::ERR_INVALID_VALUE;
2067                 break;
2068             }
2069         }
2070     } else {
2071         switch (option) {
2072             case 'h': {
2073                 // 'bm dump-dependencies -h'
2074                 // 'bm dump-dependencies --help'
2075                 result = OHOS::ERR_INVALID_VALUE;
2076                 break;
2077             }
2078             case 'n': {
2079                 // 'bm dump-dependencies -n xxx'
2080                 // 'bm dump-dependencies --bundle-name xxx'
2081                 bundleName = optarg;
2082                 break;
2083             }
2084             case 'm': {
2085                 // 'bm dump-dependencies -m xxx'
2086                 // 'bm dump-dependencies --module-name xxx'
2087                 moduleName = optarg;
2088                 break;
2089             }
2090             default: {
2091                 result = OHOS::ERR_INVALID_VALUE;
2092                 break;
2093             }
2094         }
2095     }
2096     return result;
2097 }
2098 
DumpSharedDependencies(const std::string & bundleName,const std::string & moduleName) const2099 std::string BundleManagerShellCommand::DumpSharedDependencies(const std::string &bundleName,
2100     const std::string &moduleName) const
2101 {
2102     APP_LOGD("DumpSharedDependencies bundleName: %{public}s, moduleName: %{public}s",
2103         bundleName.c_str(), moduleName.c_str());
2104     std::vector<Dependency> dependencies;
2105     ErrCode ret = bundleMgrProxy_->GetSharedDependencies(bundleName, moduleName, dependencies);
2106     nlohmann::json dependenciesJson;
2107     if (ret != ERR_OK) {
2108         APP_LOGE("dump shared dependencies failed due to errcode %{public}d", ret);
2109         return std::string();
2110     } else {
2111         dependenciesJson = nlohmann::json {{DEPENDENCIES, dependencies}};
2112     }
2113     return dependenciesJson.dump(Constants::DUMP_INDENT);
2114 }
2115 
RunAsDumpSharedCommand()2116 ErrCode BundleManagerShellCommand::RunAsDumpSharedCommand()
2117 {
2118     int32_t result = OHOS::ERR_OK;
2119     int32_t counter = 0;
2120     std::string bundleName;
2121     bool dumpSharedAll = false;
2122     while (true) {
2123         counter++;
2124         int32_t option = getopt_long(argc_, argv_, SHORT_OPTIONS_DUMP_SHARED.c_str(),
2125             LONG_OPTIONS_DUMP_SHARED, nullptr);
2126         if (optind < 0 || optind > argc_) {
2127             return OHOS::ERR_INVALID_VALUE;
2128         }
2129         if (option == -1) {
2130             if (counter == 1) {
2131                 // When scanning the first argument
2132                 if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
2133                     // 'bm dump-shared' with no option: bm dump-shared
2134                     // 'bm dump-shared' with a wrong argument: bm dump-shared xxx
2135                     resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
2136                     result = OHOS::ERR_INVALID_VALUE;
2137                 }
2138             }
2139             break;
2140         }
2141         result = ParseSharedCommand(option, bundleName, dumpSharedAll);
2142         if (option == '?') {
2143             break;
2144         }
2145     }
2146     if (result != OHOS::ERR_OK) {
2147         resultReceiver_.append(HELP_MSG_DUMP_SHARED);
2148     } else if (dumpSharedAll) {
2149         std::string dumpResults = DumpSharedAll();
2150         resultReceiver_.append(dumpResults);
2151     } else {
2152         if ((resultReceiver_ == "") && (bundleName.size() == 0)) {
2153             // 'bm dump-shared -n ...' with no bundle name option
2154             resultReceiver_.append(HELP_MSG_NO_REMOVABLE_OPTION);
2155             result = OHOS::ERR_INVALID_VALUE;
2156             return result;
2157         }
2158         std::string dumpResults = DumpShared(bundleName);
2159         if (dumpResults.empty() || (dumpResults == "")) {
2160             dumpResults = HELP_MSG_DUMP_FAILED + "\n";
2161         }
2162         resultReceiver_.append(dumpResults);
2163     }
2164     return result;
2165 }
2166 
ParseSharedCommand(int32_t option,std::string & bundleName,bool & dumpSharedAll)2167 ErrCode BundleManagerShellCommand::ParseSharedCommand(int32_t option, std::string &bundleName, bool &dumpSharedAll)
2168 {
2169     int32_t result = OHOS::ERR_OK;
2170     if (option == '?') {
2171         switch (optopt) {
2172             case 'n': {
2173                 // 'bm dump-shared -n' with no argument: bm dump-shared -n
2174                 // 'bm dump-shared --bundle-name' with no argument: bm dump-shared --bundle-name
2175                 resultReceiver_.append(STRING_REQUIRE_CORRECT_VALUE);
2176                 result = OHOS::ERR_INVALID_VALUE;
2177                 break;
2178             }
2179             default: {
2180                 // 'bm dump-shared' with an unknown option: bm dump-shared -x
2181                 // 'bm dump-shared' with an unknown option: bm dump-shared -xxx
2182                 std::string unknownOption = "";
2183                 std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
2184                 resultReceiver_.append(unknownOptionMsg);
2185                 result = OHOS::ERR_INVALID_VALUE;
2186                 break;
2187             }
2188         }
2189     } else {
2190         switch (option) {
2191             case 'h': {
2192                 // 'bm dump-shared -h'
2193                 // 'bm dump-shared --help'
2194                 result = OHOS::ERR_INVALID_VALUE;
2195                 break;
2196             }
2197             case 'n': {
2198                 // 'bm dump-shared -n xxx'
2199                 // 'bm dump-shared --bundle-name xxx'
2200                 bundleName = optarg;
2201                 break;
2202             }
2203             case 'a': {
2204                 // 'bm dump-shared -a'
2205                 // 'bm dump-shared --all'
2206                 dumpSharedAll = true;
2207                 break;
2208             }
2209             default: {
2210                 result = OHOS::ERR_INVALID_VALUE;
2211                 break;
2212             }
2213         }
2214     }
2215     return result;
2216 }
2217 
DumpShared(const std::string & bundleName) const2218 std::string BundleManagerShellCommand::DumpShared(const std::string &bundleName) const
2219 {
2220     APP_LOGD("DumpShared bundleName: %{public}s", bundleName.c_str());
2221     SharedBundleInfo sharedBundleInfo;
2222     ErrCode ret = bundleMgrProxy_->GetSharedBundleInfoBySelf(bundleName, sharedBundleInfo);
2223     nlohmann::json sharedBundleInfoJson;
2224     if (ret != ERR_OK) {
2225         APP_LOGE("dump-shared failed due to errcode %{public}d", ret);
2226         return std::string();
2227     } else {
2228         sharedBundleInfoJson = nlohmann::json {{SHARED_BUNDLE_INFO, sharedBundleInfo}};
2229     }
2230     return sharedBundleInfoJson.dump(Constants::DUMP_INDENT);
2231 }
2232 
DumpSharedAll() const2233 std::string BundleManagerShellCommand::DumpSharedAll() const
2234 {
2235     APP_LOGD("DumpSharedAll");
2236     std::string dumpResults = "";
2237     std::vector<SharedBundleInfo> sharedBundleInfos;
2238     ErrCode ret = bundleMgrProxy_->GetAllSharedBundleInfo(sharedBundleInfos);
2239     if (ret != ERR_OK) {
2240         APP_LOGE("dump-shared all failed due to errcode %{public}d", ret);
2241         return dumpResults;
2242     }
2243     for (const auto& item : sharedBundleInfos) {
2244         dumpResults.append("\t");
2245         dumpResults.append(item.name);
2246         dumpResults.append("\n");
2247     }
2248     return dumpResults;
2249 }
2250 
ObtainModuleNameFromBundlePaths(const std::vector<std::string> & bundlePaths,std::string & moduleName)2251 bool BundleManagerShellCommand::ObtainModuleNameFromBundlePaths(const std::vector<std::string> &bundlePaths,
2252     std::string &moduleName)
2253 {
2254     BundleInfo info;
2255     std::vector<std::string> absPaths;
2256     GetAbsPaths(bundlePaths, absPaths);
2257     if (absPaths.empty()) {
2258         APP_LOGE("asbPaths is empty");
2259         return false;
2260     }
2261     APP_LOGD("bundlePath is %{public}s", absPaths[0].c_str());
2262     if ((!bundleMgrProxy_->GetBundleArchiveInfo(absPaths[0], BundleFlag::GET_BUNDLE_DEFAULT, info)) ||
2263         (info.moduleNames.empty())) {
2264         APP_LOGE("obtain module name failed");
2265         return false;
2266     }
2267 
2268     moduleName = info.moduleNames[0];
2269     APP_LOGD("moduleName is %{public}s", moduleName.c_str());
2270     return true;
2271 }
2272 }  // namespace AppExecFwk
2273 }  // namespace OHOS
2274