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