• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "daemon_app.h"
16 
17 namespace Hdc {
HdcDaemonApp(HTaskInfo hTaskInfo)18 HdcDaemonApp::HdcDaemonApp(HTaskInfo hTaskInfo)
19     : HdcTransferBase(hTaskInfo)
20 {
21     commandBegin = CMD_APP_BEGIN;
22     commandData = CMD_APP_DATA;
23     funcAppModFinish = nullptr;
24 }
25 
~HdcDaemonApp()26 HdcDaemonApp::~HdcDaemonApp()
27 {
28     WRITE_LOG(LOG_INFO, "~HdcDaemonApp channelId:%u", taskInfo->channelId);
29 }
30 
ReadyForRelease()31 bool HdcDaemonApp::ReadyForRelease()
32 {
33     if (!HdcTaskBase::ReadyForRelease()) {
34         WRITE_LOG(LOG_WARN, "HdcTaskBase not ready for release channelId:%u", taskInfo->channelId);
35         return false;
36     }
37     if (!asyncCommand.ReadyForRelease()) {
38         WRITE_LOG(LOG_WARN, "asyncCommand not ready for release channelId:%u", taskInfo->channelId);
39         return false;
40     }
41     WRITE_LOG(LOG_INFO, "ReadyForRelease channelId:%u", taskInfo->channelId);
42     return true;
43 }
44 
CommandDispatch(const uint16_t command,uint8_t * payload,const int payloadSize)45 bool HdcDaemonApp::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize)
46 {
47     if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) {
48         WRITE_LOG(LOG_WARN, "HdcTransferBase::CommandDispatch false command:%u channelId:%u",
49             command, taskInfo->channelId);
50         return false;
51     }
52     bool ret = true;
53     switch (command) {
54         case CMD_APP_CHECK: {
55             string dstPath = "/data/local/tmp/";
56             string bufString(reinterpret_cast<char *>(payload), payloadSize);
57             SerialStruct::ParseFromString(ctxNow.transferConfig, bufString);
58             // update transferconfig to main context
59             ctxNow.master = false;
60             ctxNow.fsOpenReq.data = &ctxNow;
61 #ifdef HDC_PCDEBUG
62             char tmpPath[256] = "";
63             size_t size = 256;
64             uv_os_tmpdir(tmpPath, &size);
65             dstPath = tmpPath;
66             dstPath += Base::GetPathSep();
67 #endif
68             dstPath += ctxNow.transferConfig.optionalName;
69             ctxNow.localPath = dstPath;
70             ctxNow.transferBegin = Base::GetRuntimeMSec();
71             ctxNow.fileSize = ctxNow.transferConfig.fileSize;
72             ++refCount;
73             uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(),
74                        UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
75                        OnFileOpen);
76             break;
77         }
78         case CMD_APP_UNINSTALL: {
79             // This maybe has a command implanting risk, since it is a controllable device, it can be ignored
80             string bufString(reinterpret_cast<char *>(payload), payloadSize);
81             string options = "";
82             string packages = "";
83             vector<string> segments;
84             Base::SplitString(bufString, " ", segments);
85             for (auto seg: segments) {
86                 if (seg[0] == '-') {
87                     options += " " + seg;
88                 } else {
89                     packages += " " + seg;
90                 }
91             }
92             PackageShell(false, options.c_str(), packages);
93             break;
94         }
95         default:
96             break;
97     }
98     return ret;
99 };
100 
AsyncInstallFinish(bool finish,int64_t exitStatus,const string result)101 bool HdcDaemonApp::AsyncInstallFinish(bool finish, int64_t exitStatus, const string result)
102 {
103     if (mode == APPMOD_INSTALL) {
104         unlink(ctxNow.localPath.c_str());
105     }
106     asyncCommand.DoRelease();
107     string echo = result;
108     echo = Base::ReplaceAll(echo, "\n", " ");
109     vector<uint8_t> vecBuf;
110     vecBuf.push_back(mode);
111     vecBuf.push_back(exitStatus == 0);
112     vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size());
113     SendToAnother(CMD_APP_FINISH, vecBuf.data(), vecBuf.size());
114     --refCount;
115 #ifdef UNIT_TEST
116     Base::WriteBinFile((UT_TMP_PATH + "/appinstall.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(),
117                        MESSAGE_SUCCESS.size(), true);
118 #endif
119     return true;
120 }
121 
PackageShell(bool installOrUninstall,const char * options,const string package)122 void HdcDaemonApp::PackageShell(bool installOrUninstall, const char *options, const string package)
123 {
124     ++refCount;
125     // asynccmd Other processes, no RunningProtect protection
126     chmod(package.c_str(), 0644);  // 0644 : permission
127     string doBuf;
128     string opts = string(options);
129     if (installOrUninstall) { // either -p or -s is always required in install
130         if (opts.find("p") == string::npos && opts.find("s") == string::npos) {
131             // basic mode: blank options or both "-s" / "-p" are omitted
132             // eg. hdc install x.hap --> bm install -p x.hap
133             // eg. hdc install -r x.hap --> bm install -r -p x.hap
134             doBuf = Base::StringFormat("bm install %s -p %s", options, package.c_str());
135         } else {
136             // advansed mode for -p/-r/-s and some other options in the future
137             doBuf = Base::StringFormat("bm install %s %s", options, package.c_str());
138         }
139     } else {  // -n is always required in uninstall
140         if (opts.find("n") == string::npos) {
141             // basic mode: blank options or "-n" is omitted
142             // eg. hdc uninstall com.xx.xx --> bm uninstall -n com.xx.xx
143             // eg. hdc uninstall -s com.xx.xx --> bm uninstall -s -n com.xx.xx
144             doBuf = Base::StringFormat("bm uninstall %s -n %s", options, package.c_str());
145         } else {
146             // advansed mode for -s/-n and some other options in the future
147             doBuf = Base::StringFormat("bm uninstall %s %s", options, package.c_str());
148         }
149     }
150 
151     funcAppModFinish = std::bind(&HdcDaemonApp::AsyncInstallFinish, this, std::placeholders::_1, std::placeholders::_2,
152                                  std::placeholders::_3);
153     if (installOrUninstall) {
154         mode = APPMOD_INSTALL;
155     } else {
156         mode = APPMOD_UNINSTALL;
157     }
158     asyncCommand.Initial(loopTask, funcAppModFinish, AsyncCmd::OPTION_COMMAND_ONETIME);
159     asyncCommand.ExecuteCommand(doBuf);
160 }
161 
Sideload(const char * pathOTA)162 void HdcDaemonApp::Sideload(const char *pathOTA)
163 {
164     mode = APPMOD_SIDELOAD;
165     LogMsg(MSG_OK, "[placeholders] sideload %s", pathOTA);
166     TaskFinish();
167     unlink(pathOTA);
168 }
169 
WhenTransferFinish(CtxFile * context)170 void HdcDaemonApp::WhenTransferFinish(CtxFile *context)
171 {
172     if (context->lastErrno > 0) {
173         constexpr int bufSize = 1024;
174         char buf[bufSize] = { 0 };
175         uv_strerror_r(static_cast<int>(-context->lastErrno), buf, bufSize);
176         WRITE_LOG(LOG_DEBUG, "HdcDaemonApp WhenTransferFinish with errno:%d", context->lastErrno);
177         LogMsg(MSG_FAIL, "Transfer App at:%lld/%lld(Bytes), Reason: %s",
178                context->indexIO, context->fileSize, buf);
179         return;
180     }
181     if (ctxNow.transferConfig.functionName == CMDSTR_APP_SIDELOAD) {
182         Sideload(context->localPath.c_str());
183     } else if (ctxNow.transferConfig.functionName == CMDSTR_APP_INSTALL) {
184         PackageShell(true, context->transferConfig.options.c_str(), context->localPath.c_str());
185     } else {
186     }
187 };
188 }
189