1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci#include "host_app.h" 16cc290419Sopenharmony_ci#include "compress.h" 17cc290419Sopenharmony_ci 18cc290419Sopenharmony_cinamespace Hdc { 19cc290419Sopenharmony_ciHdcHostApp::HdcHostApp(HTaskInfo hTaskInfo) 20cc290419Sopenharmony_ci : HdcTransferBase(hTaskInfo) 21cc290419Sopenharmony_ci{ 22cc290419Sopenharmony_ci commandBegin = CMD_APP_BEGIN; 23cc290419Sopenharmony_ci commandData = CMD_APP_DATA; 24cc290419Sopenharmony_ci originLocalDir = ""; 25cc290419Sopenharmony_ci isStableBuf = hTaskInfo->isStableBuf; 26cc290419Sopenharmony_ci} 27cc290419Sopenharmony_ci 28cc290419Sopenharmony_ciHdcHostApp::~HdcHostApp() 29cc290419Sopenharmony_ci{ 30cc290419Sopenharmony_ci} 31cc290419Sopenharmony_ci 32cc290419Sopenharmony_cistring HdcHostApp::Dir2Tar(const char *dir) 33cc290419Sopenharmony_ci{ 34cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "dir:%s", dir); 35cc290419Sopenharmony_ci string tarpath; 36cc290419Sopenharmony_ci uv_fs_t req; 37cc290419Sopenharmony_ci int r = uv_fs_lstat(nullptr, &req, dir, nullptr); 38cc290419Sopenharmony_ci uv_fs_req_cleanup(&req); 39cc290419Sopenharmony_ci if (r == 0 && (req.statbuf.st_mode & S_IFDIR)) { // is dir 40cc290419Sopenharmony_ci string sdir = dir; 41cc290419Sopenharmony_ci string tarname = Base::GetRandomString(EXPECTED_LEN) + ".tar"; 42cc290419Sopenharmony_ci tarpath = Base::GetTmpDir() + tarname; 43cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "tarpath:%s", tarpath.c_str()); 44cc290419Sopenharmony_ci Compress c; 45cc290419Sopenharmony_ci c.UpdataPrefix(sdir); 46cc290419Sopenharmony_ci c.AddPath(sdir); 47cc290419Sopenharmony_ci c.SaveToFile(tarpath); 48cc290419Sopenharmony_ci } 49cc290419Sopenharmony_ci return tarpath; 50cc290419Sopenharmony_ci} 51cc290419Sopenharmony_ci 52cc290419Sopenharmony_cibool HdcHostApp::BeginInstall(CtxFile *context, const char *command) 53cc290419Sopenharmony_ci{ 54cc290419Sopenharmony_ci int argc = 0; 55cc290419Sopenharmony_ci bool ret = false; 56cc290419Sopenharmony_ci string options; 57cc290419Sopenharmony_ci char **argv = Base::SplitCommandToArgs(command, &argc); 58cc290419Sopenharmony_ci if (argc < 1) { 59cc290419Sopenharmony_ci goto Finish; 60cc290419Sopenharmony_ci } 61cc290419Sopenharmony_ci 62cc290419Sopenharmony_ci for (int i = 0; i < argc; ++i) { 63cc290419Sopenharmony_ci if (!strcmp(argv[i], CMD_OPTION_CLIENTCWD.c_str())) { 64cc290419Sopenharmony_ci if (i + 1 < argc) { 65cc290419Sopenharmony_ci context->transferConfig.clientCwd = argv[i + 1]; 66cc290419Sopenharmony_ci i += 1; // add content index 67cc290419Sopenharmony_ci } 68cc290419Sopenharmony_ci } else if (!strncmp(argv[i], "-", 1)) { 69cc290419Sopenharmony_ci if (options.size()) { 70cc290419Sopenharmony_ci options += " "; 71cc290419Sopenharmony_ci } 72cc290419Sopenharmony_ci options += argv[i]; 73cc290419Sopenharmony_ci } else { 74cc290419Sopenharmony_ci string path = argv[i]; 75cc290419Sopenharmony_ci ExtractRelativePath(context->transferConfig.clientCwd, path); 76cc290419Sopenharmony_ci if (MatchPackageExtendName(path, ".hap") || MatchPackageExtendName(path, ".hsp")) { 77cc290419Sopenharmony_ci context->taskQueue.push_back(path); 78cc290419Sopenharmony_ci } else { 79cc290419Sopenharmony_ci string tarpath = Dir2Tar(path.c_str()); 80cc290419Sopenharmony_ci if (!tarpath.empty()) { 81cc290419Sopenharmony_ci context->taskQueue.push_back(tarpath); 82cc290419Sopenharmony_ci originLocalDir = path; 83cc290419Sopenharmony_ci } 84cc290419Sopenharmony_ci } 85cc290419Sopenharmony_ci } 86cc290419Sopenharmony_ci } 87cc290419Sopenharmony_ci if (!context->taskQueue.size()) { 88cc290419Sopenharmony_ci LogMsg(MSG_FAIL, "Not any installation package was found"); 89cc290419Sopenharmony_ci goto Finish; 90cc290419Sopenharmony_ci } 91cc290419Sopenharmony_ci // remove repeate 92cc290419Sopenharmony_ci sort(context->taskQueue.begin(), context->taskQueue.end()); 93cc290419Sopenharmony_ci context->taskQueue.erase(unique(context->taskQueue.begin(), context->taskQueue.end()), context->taskQueue.end()); 94cc290419Sopenharmony_ci 95cc290419Sopenharmony_ci context->transferConfig.options = options; 96cc290419Sopenharmony_ci context->transferConfig.functionName = CMDSTR_APP_INSTALL; 97cc290419Sopenharmony_ci ret = RunQueue(context); 98cc290419Sopenharmony_ciFinish: 99cc290419Sopenharmony_ci if (argv) { 100cc290419Sopenharmony_ci delete[](reinterpret_cast<char *>(argv)); 101cc290419Sopenharmony_ci } 102cc290419Sopenharmony_ci return ret; 103cc290419Sopenharmony_ci} 104cc290419Sopenharmony_ci 105cc290419Sopenharmony_cibool HdcHostApp::BeginSideload(CtxFile *context, const char *localPath) 106cc290419Sopenharmony_ci{ 107cc290419Sopenharmony_ci bool ret = false; 108cc290419Sopenharmony_ci context->transferConfig.functionName = CMDSTR_APP_SIDELOAD; 109cc290419Sopenharmony_ci context->taskQueue.push_back(localPath); 110cc290419Sopenharmony_ci ret = RunQueue(context); 111cc290419Sopenharmony_ci return ret; 112cc290419Sopenharmony_ci} 113cc290419Sopenharmony_ci 114cc290419Sopenharmony_cibool HdcHostApp::RunQueue(CtxFile *context) 115cc290419Sopenharmony_ci{ 116cc290419Sopenharmony_ci context->localPath = context->taskQueue.back(); 117cc290419Sopenharmony_ci uv_fs_t *openReq = new uv_fs_t; 118cc290419Sopenharmony_ci if (openReq == nullptr) { 119cc290419Sopenharmony_ci LogMsg(MSG_FAIL, "HdcHostApp::RunQueue new uv_fs_t failed"); 120cc290419Sopenharmony_ci OnFileOpenFailed(context); 121cc290419Sopenharmony_ci return false; 122cc290419Sopenharmony_ci } 123cc290419Sopenharmony_ci memset_s(openReq, sizeof(uv_fs_t), 0, sizeof(uv_fs_t)); 124cc290419Sopenharmony_ci openReq->data = context; 125cc290419Sopenharmony_ci ++refCount; 126cc290419Sopenharmony_ci uv_fs_open(loopTask, openReq, context->localPath.c_str(), O_RDONLY, 0, OnFileOpen); 127cc290419Sopenharmony_ci context->master = true; 128cc290419Sopenharmony_ci return true; 129cc290419Sopenharmony_ci} 130cc290419Sopenharmony_ci 131cc290419Sopenharmony_civoid HdcHostApp::CheckMaster(CtxFile *context) 132cc290419Sopenharmony_ci{ 133cc290419Sopenharmony_ci uv_fs_t fs = {}; 134cc290419Sopenharmony_ci uv_fs_fstat(nullptr, &fs, context->openFd, nullptr); 135cc290419Sopenharmony_ci context->transferConfig.fileSize = fs.statbuf.st_size; 136cc290419Sopenharmony_ci uv_fs_req_cleanup(&fs); 137cc290419Sopenharmony_ci 138cc290419Sopenharmony_ci context->transferConfig.optionalName 139cc290419Sopenharmony_ci = Base::GetRandomString(EXPECTED_LEN); // Prevent the name of illegal APP leads to pm unable to install 140cc290419Sopenharmony_ci if (context->localPath.find(".hap") != static_cast<size_t>(-1)) { 141cc290419Sopenharmony_ci context->transferConfig.optionalName += ".hap"; 142cc290419Sopenharmony_ci } else if (context->localPath.find(".hsp") != static_cast<size_t>(-1)) { 143cc290419Sopenharmony_ci context->transferConfig.optionalName += ".hsp"; 144cc290419Sopenharmony_ci } else if (context->localPath.find(".tar") != static_cast<size_t>(-1)) { 145cc290419Sopenharmony_ci context->transferConfig.optionalName += ".tar"; 146cc290419Sopenharmony_ci } else { 147cc290419Sopenharmony_ci context->transferConfig.optionalName += ".bundle"; 148cc290419Sopenharmony_ci } 149cc290419Sopenharmony_ci string bufString = SerialStruct::SerializeToString(context->transferConfig); 150cc290419Sopenharmony_ci SendToAnother(CMD_APP_CHECK, const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bufString.c_str())), 151cc290419Sopenharmony_ci bufString.size()); 152cc290419Sopenharmony_ci} 153cc290419Sopenharmony_ci 154cc290419Sopenharmony_cibool HdcHostApp::CheckInstallContinue(AppModType mode, bool lastResult, const char *msg) 155cc290419Sopenharmony_ci{ 156cc290419Sopenharmony_ci string modeDesc; 157cc290419Sopenharmony_ci switch (mode) { 158cc290419Sopenharmony_ci case APPMOD_INSTALL: 159cc290419Sopenharmony_ci modeDesc = "App install"; 160cc290419Sopenharmony_ci break; 161cc290419Sopenharmony_ci case APPMOD_UNINSTALL: 162cc290419Sopenharmony_ci modeDesc = "App uninstall"; 163cc290419Sopenharmony_ci break; 164cc290419Sopenharmony_ci case APPMOD_SIDELOAD: 165cc290419Sopenharmony_ci modeDesc = "Side load"; 166cc290419Sopenharmony_ci break; 167cc290419Sopenharmony_ci default: 168cc290419Sopenharmony_ci modeDesc = "Unknown"; 169cc290419Sopenharmony_ci break; 170cc290419Sopenharmony_ci } 171cc290419Sopenharmony_ci if (ctxNow.taskQueue.size() > 0) { 172cc290419Sopenharmony_ci string path = ctxNow.taskQueue.back(); 173cc290419Sopenharmony_ci ctxNow.taskQueue.pop_back(); 174cc290419Sopenharmony_ci string::size_type pos = path.rfind(".tar"); 175cc290419Sopenharmony_ci if (mode == APPMOD_INSTALL && pos != string::npos) { 176cc290419Sopenharmony_ci unlink(path.c_str()); 177cc290419Sopenharmony_ci WRITE_LOG(LOG_DEBUG, "unlink path:%s", path.c_str()); 178cc290419Sopenharmony_ci } 179cc290419Sopenharmony_ci } 180cc290419Sopenharmony_ci string path = ctxNow.localPath; 181cc290419Sopenharmony_ci if (!originLocalDir.empty()) { 182cc290419Sopenharmony_ci path = originLocalDir; 183cc290419Sopenharmony_ci } 184cc290419Sopenharmony_ci LogMsg(MSG_INFO, "%s path:%s msg:%s", modeDesc.c_str(), path.c_str(), msg + printedMsgLen); 185cc290419Sopenharmony_ci printedMsgLen = strlen(msg); 186cc290419Sopenharmony_ci if (singalStop || !ctxNow.taskQueue.size()) { 187cc290419Sopenharmony_ci LogMsg(MSG_OK, "AppMod finish"); 188cc290419Sopenharmony_ci return false; 189cc290419Sopenharmony_ci } 190cc290419Sopenharmony_ci return RunQueue(&ctxNow); 191cc290419Sopenharmony_ci} 192cc290419Sopenharmony_ci 193cc290419Sopenharmony_cibool HdcHostApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) 194cc290419Sopenharmony_ci{ 195cc290419Sopenharmony_ci if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { 196cc290419Sopenharmony_ci return false; 197cc290419Sopenharmony_ci } 198cc290419Sopenharmony_ci bool ret = true; 199cc290419Sopenharmony_ci constexpr int cmdOffset = 2; 200cc290419Sopenharmony_ci switch (command) { 201cc290419Sopenharmony_ci case CMD_APP_INIT: { 202cc290419Sopenharmony_ci ret = BeginInstall(&ctxNow, (const char *)payload); 203cc290419Sopenharmony_ci break; 204cc290419Sopenharmony_ci } 205cc290419Sopenharmony_ci case CMD_APP_FINISH: { 206cc290419Sopenharmony_ci AppModType mode = static_cast<AppModType>(payload[0]); 207cc290419Sopenharmony_ci bool result = static_cast<bool>(payload[1]); 208cc290419Sopenharmony_ci string s(reinterpret_cast<char *>(payload + cmdOffset), payloadSize - cmdOffset); 209cc290419Sopenharmony_ci ret = CheckInstallContinue(mode, result, s.c_str()); 210cc290419Sopenharmony_ci break; 211cc290419Sopenharmony_ci } 212cc290419Sopenharmony_ci case CMD_APP_UNINSTALL: { 213cc290419Sopenharmony_ci SendToAnother(CMD_APP_UNINSTALL, payload, payloadSize); 214cc290419Sopenharmony_ci ctxNow.taskQueue.push_back(reinterpret_cast<char *>(payload)); // just compatible 215cc290419Sopenharmony_ci break; 216cc290419Sopenharmony_ci } 217cc290419Sopenharmony_ci case CMD_APP_SIDELOAD: { 218cc290419Sopenharmony_ci BeginSideload(&ctxNow, (const char *)payload); 219cc290419Sopenharmony_ci break; 220cc290419Sopenharmony_ci } 221cc290419Sopenharmony_ci default: 222cc290419Sopenharmony_ci break; 223cc290419Sopenharmony_ci } 224cc290419Sopenharmony_ci return ret; 225cc290419Sopenharmony_ci}; 226cc290419Sopenharmony_ci} 227