• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 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 
16 #include "command_parser.h"
17 
18 #include <climits>
19 #include <cstdint>
20 #include <getopt.h>
21 #include <iostream>
22 #include <pthread.h>
23 #include <semaphore.h>
24 
25 #include "adapter.h"
26 #include "appexecfwk_errors.h"
27 #include "bundle_info.h"
28 #include "bundle_inner_interface.h"
29 #include "bundle_manager.h"
30 #include "convert_utils.h"
31 #include "iproxy_client.h"
32 #include "ipc_skeleton.h"
33 #include "parameter.h"
34 #include "samgr_lite.h"
35 #include "securec.h"
36 #include "rpc_errno.h"
37 
38 using namespace std;
39 
40 namespace OHOS {
41 namespace {
42 const int32_t MIN_ARGUMENT_NUMBER = 2;
43 const int32_t MAX_ARGUMENT_NUMBER = 4;
44 const int32_t MAX_LOG_LEN = 1024;
45 const int32_t MAX_DUMP_LIST_NUMBER = 3;
46 const int32_t UDID_STRING_LEN = 64;
47 const uint32_t INITIAL_CBID = 1;
48 
49 static sem_t g_sem;
50 static IClientProxy *g_bmsInnerClient = nullptr;
51 static InstallParam g_installParam = { .installLocation = 1, .keepData = false };
52 
53 const std::string CMD_INSTALL = "install";
54 const std::string CMD_UNINSTALL = "uninstall";
55 const std::string CMD_DUMP = "dump";
56 const std::string CMD_ENABLE = "set";
57 const std::string CMD_GET_UDID = "getudid";
58 
59 const std::string INSTALL_HELP_MESSAGE = "Usage: install hap-path [options]\n"
60                                    "Description:\n"
61                                    "\t--help|-h                   help menu\n"
62                                    "\t--happath|-p           location of the hap to install\n";
63 const std::string UNINSTALL_HELP_MESSAGE = "Usage: uninstall bundle-name [options]\n"
64                                      "Description:\n"
65                                      "\t--help|-h                   help menu\n"
66                                      "\t--bundlename|-n           name of the bundle to uninstall\n";
67 const std::string DUMP_HELP_MESSAGE = "Usage: dump [options]\n"
68                                       "Option Description:\n"
69                                       "\t--help|-h                   help menu\n"
70                                       "\t--list|-l                   app list\n"
71                                       "\t--bundlename|-n           dump installed hap's info\n"
72                                       "\t--metadatakey|-m           dump bundleNames match metaData key\n";
73 const std::string ENABLE_HELP_MESSAGE = "Usage: set [options]\n"
74                                         "Option Description:\n"
75                                         "\t--externalmode|-e status    enable externalmode\n"
76                                         "\t--debugmode|-d  status      enable debugmode\n"
77                                         "\t--signmode|-s  status      enable signmode\n";
78 
79 const std::string HELP_MESSAGE = INSTALL_HELP_MESSAGE + UNINSTALL_HELP_MESSAGE + DUMP_HELP_MESSAGE +
80     ENABLE_HELP_MESSAGE;
81 const std::string ERROR_COMMAND = "error command!\n";
82 const std::string ERROR_OPTION = "error option!\n";
83 const std::string ERROR_INSTALL_PATH = "invalid path!\n";
84 const std::string ERROR_EXTRA_PARAMETER = "extra parameter!\n";
85 const std::string ERROR_SEM_ERROR = "sem init failed!\n";
86 const std::string ERROR_DUMP_FAIL = "no bundle info!\n";
87 const std::string ERROR_DUMP_ERROR = "dump info error!\n";
88 
89 const std::string SHORT_OPTIONS = "n:hlp:m:";
90 const struct option LONG_OPTIONS[] = {
91     {"help", no_argument, nullptr, 'h'},
92     {"list", no_argument, nullptr, 'l'},
93     {"bundlename", required_argument, nullptr, 'n'},
94     {"happath", required_argument, nullptr, 'p'},
95     {"metadatakey", required_argument, nullptr, 'm'},
96     {nullptr, 0, nullptr, 0}
97 };
98 
99 #ifdef OHOS_DEBUG
100 const std::string ENABLE_SHORT_OPTIONS = "he:d:s:";
101 const struct option ENABLE_LONG_OPTIONS[] = {
102     {"help", no_argument, nullptr, 'h'},
103     {"externalmode", required_argument, nullptr, 'e'},
104     {"debugmode", required_argument, nullptr, 'd'},
105     {"signmode", required_argument, nullptr, 's'},
106     {nullptr, 0, nullptr, 0}
107 };
108 #endif
109 
GetBmsInnerClient()110 IClientProxy *GetBmsInnerClient()
111 {
112     IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BMS_SERVICE, BMS_INNER_FEATURE);
113     if (iUnknown == nullptr) {
114         printf("get feature api fail!\n");
115         return nullptr;
116     }
117     IClientProxy *bmsClient = nullptr;
118     int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, reinterpret_cast<void **>(&bmsClient));
119     if (result != 0) {
120         printf("query interface fail!\n");
121         return nullptr;
122     }
123     return bmsClient;
124 }
125 } // namespace
126 
HandleCommands(int32_t argc,char * argv[]) const127 void CommandParser::HandleCommands(int32_t argc, char *argv[]) const
128 {
129     if (argc < MIN_ARGUMENT_NUMBER) {
130         printf("%s\n", HELP_MESSAGE.c_str());
131         return;
132     }
133     g_bmsInnerClient = GetBmsInnerClient();
134     std::string cmd = argv[1];
135     if (cmd == CMD_INSTALL) {
136         RunAsInstallCommand(argc, argv);
137     } else if (cmd == CMD_UNINSTALL) {
138         RunAsUninstallCommand(argc, argv);
139     } else if (cmd == CMD_DUMP) {
140         RunAsDumpCommand(argc, argv);
141     } else if (cmd == CMD_GET_UDID) {
142         RunAsGetUdidCommand(argc, argv);
143 #ifdef OHOS_DEBUG
144     } else if (cmd == CMD_ENABLE) {
145         RunAsEnableCommand(argc, argv);
146 #endif
147     } else {
148         printf("%s\n", (ERROR_COMMAND + HELP_MESSAGE).c_str());
149     }
150 }
151 
ReceiveCallback(const uint8_t resultCode,const void * resultMessage)152 static void ReceiveCallback(const uint8_t resultCode, const void *resultMessage)
153 {
154     std::string strMessage = reinterpret_cast<const char *>(resultMessage);
155     if (!strMessage.empty()) {
156         printf("resultMessage is %s\n", strMessage.c_str());
157     }
158     sem_post(&g_sem);
159 }
160 
BmToolDeathNotify(void * arg)161 static void BmToolDeathNotify(void *arg)
162 {
163     printf("error message: %s\n", "Bundle Manager Service is dead");
164     exit(-1);
165 }
166 
RunAsInstallCommand(int32_t argc,char * argv[]) const167 void CommandParser::RunAsInstallCommand(int32_t argc, char *argv[]) const
168 {
169     if (argc > MAX_ARGUMENT_NUMBER) {
170         printf("%s\n", (ERROR_EXTRA_PARAMETER + INSTALL_HELP_MESSAGE).c_str());
171         return;
172     }
173 
174     int32_t option;
175     char realPath[PATH_MAX + 1] = { 0 };
176     uint32_t cbId = INITIAL_CBID;
177     SvcIdentity sid = SAMGR_GetRemoteIdentity(BMS_SERVICE, BMS_INNER_FEATURE);
178     while ((option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
179         switch (option) {
180             case 'h':
181                 printf("%s\n", INSTALL_HELP_MESSAGE.c_str());
182                 break;
183             case 'p':
184                 if (sem_init(&g_sem, 0, 0)) {
185                     printf("error message: %s\n", ERROR_SEM_ERROR.c_str());
186                     return;
187                 }
188                 if (optarg == nullptr || strlen(optarg) > PATH_MAX) {
189                     printf("error message: %s\n", ERROR_INSTALL_PATH.c_str());
190                     return;
191                 }
192                 if (realpath(optarg, realPath) == nullptr) {
193                     printf("error message: %s\n", ERROR_INSTALL_PATH.c_str());
194                     return;
195                 }
196                 if (AddDeathRecipient(sid, BmToolDeathNotify, nullptr, &cbId) != ERR_NONE) {
197                     printf("error message: %s\n", "death callback is registered unsuccessfully");
198                     return;
199                 }
200                 Install(realPath, &g_installParam, ReceiveCallback);
201                 sem_wait(&g_sem);
202                 break;
203             default:
204                 printf("%s\n", (ERROR_OPTION + INSTALL_HELP_MESSAGE).c_str());
205                 break;
206         }
207     }
208 }
209 
RunAsUninstallCommand(int32_t argc,char * argv[]) const210 void CommandParser::RunAsUninstallCommand(int32_t argc, char *argv[]) const
211 {
212     if (argc > MAX_ARGUMENT_NUMBER) {
213         printf("%s\n", (ERROR_EXTRA_PARAMETER + UNINSTALL_HELP_MESSAGE).c_str());
214         return;
215     }
216 
217     int32_t option;
218     uint32_t cbId = INITIAL_CBID;
219     SvcIdentity sid = SAMGR_GetRemoteIdentity(BMS_SERVICE, BMS_INNER_FEATURE);
220     while ((option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
221         switch (option) {
222             case 'h':
223                 printf("%s\n", UNINSTALL_HELP_MESSAGE.c_str());
224                 break;
225             case 'n':
226                 if (sem_init(&g_sem, 0, 0)) {
227                     printf("error message: %s\n", ERROR_SEM_ERROR.c_str());
228                     return;
229                 }
230                 if (AddDeathRecipient(sid, BmToolDeathNotify, nullptr, &cbId) != ERR_NONE) {
231                     printf("error message: %s\n", "death callback is registered unsuccessfully");
232                     return;
233                 }
234                 Uninstall(optarg, &g_installParam, ReceiveCallback);
235                 sem_wait(&g_sem);
236                 break;
237             default:
238                 printf("%s\n", (ERROR_OPTION + UNINSTALL_HELP_MESSAGE).c_str());
239                 break;
240         }
241     }
242 }
243 
RunAsDumpCommand(int32_t argc,char * argv[]) const244 void CommandParser::RunAsDumpCommand(int32_t argc, char *argv[]) const
245 {
246     if (argc > MAX_ARGUMENT_NUMBER) {
247         printf("%s\n", (ERROR_EXTRA_PARAMETER + DUMP_HELP_MESSAGE).c_str());
248         return;
249     }
250 
251     int32_t option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
252     switch (option) {
253         case 'h':
254             printf("%s\n", DUMP_HELP_MESSAGE.c_str());
255             break;
256         case 'n':
257             GetInstallBundleInfo(optarg);
258             break;
259         case 'l':
260             GetInstallBundleInfos(argc);
261             break;
262         case 'm':
263             GetBundleInfosByMetaDataKey(optarg);
264             break;
265         default:
266             printf("%s\n", (ERROR_OPTION + DUMP_HELP_MESSAGE).c_str());
267             break;
268     }
269 }
270 
RunAsGetUdidCommand(int32_t argc,char * argv[]) const271 void CommandParser::RunAsGetUdidCommand(int32_t argc, char *argv[]) const
272 {
273     if (argc > MAX_ARGUMENT_NUMBER) {
274         printf("%s\n", (ERROR_EXTRA_PARAMETER + DUMP_HELP_MESSAGE).c_str());
275         return;
276     }
277 
278     char udid[UDID_STRING_LEN + 1] = {0};
279     if (memset_s(udid, sizeof(udid), 0, sizeof(udid)) != EOK) {
280         printf("GetUdid error memset\n");
281         return;
282     }
283     char *devUdid = udid;
284     int ret = GetDevUdid(devUdid, sizeof(udid));
285     if (ret == EOK) {
286         cout << devUdid << endl;
287     } else {
288         cout << "Get Udid error ret = " << ret << endl;
289     }
290 }
291 
292 #ifdef OHOS_DEBUG
RunAsEnableCommand(int32_t argc,char * argv[]) const293 void CommandParser::RunAsEnableCommand(int32_t argc, char *argv[]) const
294 {
295     if (argc > MAX_ARGUMENT_NUMBER) {
296         printf("%s\n", (ERROR_EXTRA_PARAMETER + ENABLE_HELP_MESSAGE).c_str());
297         return;
298     }
299 
300     int32_t option = getopt_long_only(argc, argv, ENABLE_SHORT_OPTIONS.c_str(), ENABLE_LONG_OPTIONS, nullptr);
301     switch (option) {
302         case 'h':
303             printf("%s\n", ENABLE_HELP_MESSAGE.c_str());
304             break;
305         case 'd':
306             SetDebugMode(optarg, SET_SIGN_DEBUG_MODE);
307             break;
308         case 'e':
309             SetDebugMode(optarg, SET_EXTERNAL_INSTALL_MODE);
310             break;
311         case 's':
312             SetDebugMode(optarg, SET_SIGN_MODE);
313             break;
314         default:
315             printf("%s\n", (ERROR_OPTION + ENABLE_HELP_MESSAGE).c_str());
316             break;
317     }
318 }
319 #endif
320 
GetInstallBundleInfo(const std::string & bundleName) const321 void CommandParser::GetInstallBundleInfo(const std::string &bundleName) const
322 {
323     BundleInfo bundleInfo;
324     if (memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)) != EOK) {
325         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
326         return;
327     }
328     if (GetBundleInfo(bundleName.c_str(), 1, &bundleInfo) != OHOS_SUCCESS) {
329         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
330         return;
331     }
332 
333     cJSON *root = ConvertUtils::GetJsonBundleInfo(&bundleInfo);
334     if (root == nullptr) {
335         ClearBundleInfo(&bundleInfo);
336         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
337         return;
338     }
339 
340     char *str = cJSON_PrintUnformatted(root);
341     cJSON_Delete(root);
342     ClearBundleInfo(&bundleInfo);
343     if (str != nullptr) {
344         InfoPrint(str);
345         cJSON_free(str);
346         str = nullptr;
347     } else {
348         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
349     }
350 }
351 
InfoPrint(const std::string & str) const352 void CommandParser::InfoPrint(const std::string &str) const
353 {
354     int32_t len = str.size();
355     if (len == 0) {
356         return;
357     }
358     int32_t times = len / MAX_LOG_LEN;
359     int32_t remains = len % MAX_LOG_LEN;
360     for (int32_t i = 0; i < times; i++) {
361         printf("%s\n", str.substr(i * MAX_LOG_LEN, MAX_LOG_LEN).c_str());
362     }
363     printf("%s\n", str.substr(times * MAX_LOG_LEN, remains).c_str());
364 }
365 
GetInstallBundleInfos(int32_t argc) const366 void CommandParser::GetInstallBundleInfos(int32_t argc) const
367 {
368     if (argc > MAX_DUMP_LIST_NUMBER) {
369         printf("error message: %s\n", ERROR_OPTION.c_str());
370         return;
371     }
372 
373     BundleInfo *bundleInfo = nullptr;
374     int32_t len = 0;
375     if (GetBundleInfos(1, &bundleInfo, &len) != OHOS_SUCCESS) {
376         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
377         return;
378     }
379 
380     cJSON *root = ConvertUtils::GetJsonBundleInfos(&bundleInfo, len);
381     if (root == nullptr) {
382         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
383         BundleInfoUtils::FreeBundleInfos(bundleInfo, len);
384         return;
385     }
386 
387     char *str = cJSON_PrintUnformatted(root);
388     cJSON_Delete(root);
389     BundleInfoUtils::FreeBundleInfos(bundleInfo, len);
390     if (str != nullptr) {
391         InfoPrint(str);
392         cJSON_free(str);
393         str = nullptr;
394     } else {
395         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
396     }
397 }
398 
GetBundleInfosByMetaDataKey(const std::string & metaDataKey) const399 void CommandParser::GetBundleInfosByMetaDataKey(const std::string &metaDataKey) const
400 {
401     int32_t len = 0;
402     BundleInfo *bundleInfos = nullptr;
403 
404     if (metaDataKey.empty()) {
405         printf("query param is invalid!\n");
406         return;
407     }
408     if (GetBundleInfosByMetaData(metaDataKey.c_str(), &bundleInfos, &len) != OHOS_SUCCESS) {
409         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
410         return;
411     }
412 
413     printf("bundleNames match metaData key, len: %d\n", len);
414     for (int32_t i = 0; i < len; ++i) {
415         printf("bundleName: %s", bundleInfos[i].bundleName);
416         if (i != len - 1) {
417             printf("%s\n", "; ");
418         } else {
419             printf("%s\n", "\n");
420         }
421     }
422     BundleInfoUtils::FreeBundleInfos(bundleInfos, len);
423 }
424 
425 #ifdef OHOS_DEBUG
BmsToolNotify(IOwner owner,int code,IpcIo * reply)426 static int BmsToolNotify(IOwner owner, int code, IpcIo *reply)
427 {
428     if ((reply == nullptr) || (owner == nullptr)) {
429         printf("%s\n", "Bm tool Notify ipc is nullptr");
430         return OHOS_FAILURE;
431     }
432     uint8_t readCode;
433     ReadUint8(reply, &readCode);
434     switch (readCode) {
435         case SET_EXTERNAL_INSTALL_MODE:
436         case SET_SIGN_DEBUG_MODE:
437         case SET_SIGN_MODE: {
438             uint8_t *ret = reinterpret_cast<uint8_t *>(owner);
439             ReadUint8(reply, ret);
440             break;
441         }
442         default: {
443             break;
444         }
445     }
446     return ERR_OK;
447 }
448 
SetMode(int32_t mode,bool enable)449 uint8_t SetMode(int32_t mode, bool enable)
450 {
451     if (g_bmsInnerClient == nullptr) {
452         printf("%s\n", "Bm tool client is nullptr");
453         return ERR_APPEXECFWK_OBJECT_NULL;
454     }
455     IpcIo ipcIo;
456     char data[MAX_IO_SIZE];
457     IpcIoInit(&ipcIo, data, MAX_IO_SIZE, 0);
458     WriteBool(&ipcIo, enable);
459     uint8_t setModeResult = 0;
460     int32_t ret = g_bmsInnerClient->Invoke(g_bmsInnerClient, mode, &ipcIo, &setModeResult, BmsToolNotify);
461     if (ret != ERR_OK) {
462         printf("Bm tool invoke failed: %d\n", ret);
463         return ERR_APPEXECFWK_INVOKE_ERROR;
464     }
465     return setModeResult;
466 }
467 
SetDebugMode(const std::string & enable,int32_t mode) const468 void CommandParser::SetDebugMode(const std::string &enable, int32_t mode) const
469 {
470     bool isEnable = false;
471     if (enable == "enable") {
472         isEnable = true;
473     } else if (enable == "disable") {
474         isEnable =  false;
475     } else {
476         printf("%s\n", "wrong param");
477         return;
478     }
479     uint8_t ret = SetMode(mode, isEnable);
480     if (ret == 0) {
481         printf("%s\n", "success");
482     } else {
483         printf("%s\n", "fail");
484     }
485 }
486 #endif
487 } // namespace OHOS
488