diff --git a/interfaces/kits/updaterkits/updaterkits.cpp b/interfaces/kits/updaterkits/updaterkits.cpp index 60ac4c5e885532adde38c32d108fdb2ffa47a7d0..bfc2a6a4ff47c3b5648d39fc1f2ec13f305d9ab7 100755 --- a/interfaces/kits/updaterkits/updaterkits.cpp +++ b/interfaces/kits/updaterkits/updaterkits.cpp @@ -39,7 +39,7 @@ static bool WriteToMiscAndRebootToUpdater(const std::string &miscFile, int32_t propertyMaxSize = 92; char updateCmd[propertyMaxSize]; void(snprintf_s(updateCmd, propertyMaxSize, propertyMaxSize - 1, "reboot,updater:%s", updateMsg.update)); - bool bRet = OHOS::system::SetParameter("sys.powerctrl", updateCmd); + bool bRet = OHOS::system::SetParameter("ohos.startup.powerctrl", updateCmd); if (!bRet) { std::cout << "WriteToMiscAndRebootToUpdater SetParameter failed, errno: " << errno << std::endl; return false; diff --git a/ohos.build b/ohos.build index 9ef224ed187070c28c6c651f8fdacf9d43cb38e7..010ef856d55e49f83f3a118fc7ec10c72a664f24 100644 --- a/ohos.build +++ b/ohos.build @@ -12,6 +12,7 @@ "//base/update/updater/services:updater", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/fs_manager:libfsmanager", + "//base/update/updater/services/flashd:updater_flashd", "//base/update/updater/utils:libutils", "//base/update/updater/utils:updater_reboot", "//base/update/updater/utils:write_updater", diff --git a/services/BUILD.gn b/services/BUILD.gn index a52c4d2931fb5893a55103d88babe6d8dddf0fb1..945f511df1ab46536a447b17e7c27a6ef91b1e24 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -95,6 +95,7 @@ ohos_executable("updater") { "//base/update/updater/interfaces/kits/packages:libpackageExt", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/flashd:libflashd", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", diff --git a/services/diffpatch/diff/blocks_diff.h b/services/diffpatch/diff/blocks_diff.h index dc682eac4d3b7e9e10d9b894577d8b098b4b323b..5dd76fa949cf8e203429ca837ef48c9d33804119 100644 --- a/services/diffpatch/diff/blocks_diff.h +++ b/services/diffpatch/diff/blocks_diff.h @@ -89,7 +89,7 @@ public: private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; + int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; std::fstream &stream_; size_t offset_ { 0 }; }; @@ -102,7 +102,7 @@ public: private: std::unique_ptr CreateBZip2Adapter(size_t patchOffset) override; int32_t WritePatchHeader(int64_t controlSize, - int64_t diffDataSize, int64_t newSize, size_t &patchOffset) override; + int64_t diffDataSize, int64_t newSize, size_t &headerLen) override; std::vector &patchData_; size_t offset_ { 0 }; }; diff --git a/services/etc/init.cfg b/services/etc/init.cfg index cefe21d4de5f8fb77a765a7c5cb690f99da80441..a1f12f5dc0fd0e79f6bc05ef28786761619a5356 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -14,9 +14,11 @@ "mkdir /system", "mkdir /vendor", "mkdir /tmp", + "mkdir /param", "mount tmpfs tmpfs /tmp", "chown 0 2000 /tmp", "chmod 0755 /tmp", + "chmod 0755 /param", "mkdir /dev/usb-ffs 0770 shell shell", "mkdir /dev/usb-ffs/hdc 0770 shell shell", "mkdir /dev/usb-ffs/hdc 0770 shell shell", @@ -40,6 +42,7 @@ "write /config/usb_gadget/g1/configs/b.1/MaxPower 500", "symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1", "mount functionfs hdc /dev/usb-ffs/hdc uid=2000,gid=2000", + "load_persist_params ", "setparam sys.usb.controller 100e0000.hidwc3_0", "setparam sys.usb.config hdc", "setparam sys.usb.configfs 1" @@ -65,7 +68,6 @@ "path" : ["/bin/updater"], "uid" : 0, "gid" : 0, - "once" : 1, "importance" : 0, "caps" : [0, 1] }, { diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn index d484a64c5442abdb889e18d9e032138720cbeff2..ab998573d1075c16c27401362b393b39cc759cf6 100755 --- a/services/flashd/BUILD.gn +++ b/services/flashd/BUILD.gn @@ -13,6 +13,86 @@ import("//build/ohos.gni") +FLASHD_PATH = "//base/update/updater/services/flashd" +HDC_PATH = "//developtools/hdc_standard/src" + +common_sources = [ + "${HDC_PATH}/common/async_cmd.cpp", + "${HDC_PATH}/common/auth.cpp", + "${HDC_PATH}/common/base.cpp", + "${HDC_PATH}/common/channel.cpp", + "${HDC_PATH}/common/debug.cpp", + "${HDC_PATH}/common/file.cpp", + "${HDC_PATH}/common/file_descriptor.cpp", + "${HDC_PATH}/common/forward.cpp", + "${HDC_PATH}/common/session.cpp", + "${HDC_PATH}/common/task.cpp", + "${HDC_PATH}/common/tcp.cpp", + "${HDC_PATH}/common/transfer.cpp", + "${HDC_PATH}/common/usb.cpp", +] + +config("flashd_hdc_config") { + include_dirs = [ "${FLASHD_PATH}/common" ] + cflags_cc = [ "-std=c++17" ] +} + +ohos_source_set("flashd_deamon") { + sources = [ + "${FLASHD_PATH}/daemon/daemon.cpp", + "${FLASHD_PATH}/daemon/daemon_unity.cpp", + "${HDC_PATH}/daemon/daemon_app.cpp", + "${HDC_PATH}/daemon/daemon_forward.cpp", + "${HDC_PATH}/daemon/daemon_tcp.cpp", + "${HDC_PATH}/daemon/daemon_usb.cpp", + "${HDC_PATH}/daemon/jdwp.cpp", + "${HDC_PATH}/daemon/shell.cpp", + ] + + sources += common_sources + + defines = [ + "HARMONY_PROJECT", + "HDC_SUPPORT_FLASHD", + ] + + configs = [ ":flashd_hdc_config" ] + + deps = [ + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utils", + ] + + if (use_musl) { + deps += [ + "//base/startup/init_lite/interfaces/innerkits/reboot:libreboot_static", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + ] + } + + include_dirs = [ + "${HDC_PATH}/daemon", + "${HDC_PATH}/common", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/common", + "//base/update/updater/services/flashd/host", + "//utils/native/base/include", + "//third_party/lz4/lib", + "//third_party/openssl/include", + "//third_party/libuv", + ] + + if (use_musl) { + include_dirs += [ + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", + "//base/startup/init_lite/interfaces/innerkits/include", + ] + } +} + ohos_static_library("libflashd") { sources = [ "//base/update/updater/services/flashd/blockdevice.cpp", @@ -26,12 +106,12 @@ ohos_static_library("libflashd") { ] defines = [ - "HDC_DEBUG", "HDC_SUPPORT_FLASHD", "HARMONY_PROJECT", ] deps = [ + ":flashd_deamon", "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/patch:libpatch", @@ -40,23 +120,22 @@ ohos_static_library("libflashd") { "//base/update/updater/services/package:libupdaterpackage", "//base/update/updater/services/script:libupdaterscript", "//base/update/updater/utils:libutils", - "//developtools/hdc_standard:hdc_deamon_flashd", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", - "//third_party/openssl:ssl_source", "//third_party/zlib:libz", "//utils/native/base:utils", ] include_dirs = [ - "//developtools/hdc_standard/src/daemon", - "//developtools/hdc_standard/src/common", + "${HDC_PATH}/daemon", + "${HDC_PATH}/common", "//base/update/updater/services", "//base/update/updater/services/flashd", "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/common", "//base/update/updater/interfaces/kits/include", "//base/update/updater/services/include/package", "//base/update/updater/services/include/script", @@ -75,6 +154,92 @@ ohos_static_library("libflashd") { part_name = "updater" } +ohos_executable("ohflash") { + libs = [] + configs = [ ":flashd_hdc_config" ] + defines = [ + "HDC_HOST", + "HARMONY_PROJECT", + ] + if (is_mac) { + defines += [ "HOST_MAC" ] + } + cflags_cc = [ + "-Wno-error", + "-Wno-error=unused-variable", + "-Wno-unused-variable", + ] + sources = [ + "${FLASHD_PATH}/host/client.cpp", + "${FLASHD_PATH}/host/host_updater.cpp", + "${FLASHD_PATH}/host/main.cpp", + "${FLASHD_PATH}/host/server.cpp", + "${FLASHD_PATH}/host/server_for_client.cpp", + "${FLASHD_PATH}/host/translate.cpp", + "${HDC_PATH}/host/host_app.cpp", + "${HDC_PATH}/host/host_forward.cpp", + "${HDC_PATH}/host/host_tcp.cpp", + "${HDC_PATH}/host/host_unity.cpp", + "${HDC_PATH}/host/host_usb.cpp", + ] + sources += common_sources + + deps = [ + "//third_party/libusb:libusb", + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + "//utils/native/base:utilsecurec", + ] + + deps += [ "//third_party/libusb:libusb" ] + + include_dirs = [ + "${FLASHD_PATH}/host", + "${HDC_PATH}/host", + "${FLASHD_PATH}/common", + "${HDC_PATH}/common", + "//utils/native/base/include", + "//third_party/lz4/lib", + "//third_party/openssl/include", + "//third_party/libuv", + ] + + if (is_mingw) { + static_link = true + defines += [ "_WIN32" ] + defines += [ "WIN32_LEAN_AND_MEAN" ] + libs += [ "setupapi" ] + } + + if (is_linux) { + static_link = true + deps += [ "//third_party/openssl:libcrypto_static" ] + } + + subsystem_name = "updater" + part_name = "updater" +} + +group("flashhost_target_standard") { + deps = [ ":ohflash" ] +} + +group("flashhost_target_standard_linux") { + deps = [ ":ohflash(//build/toolchain/linux:clang_x64)" ] +} + +group("flashhost_target_standard_mingw") { + deps = [ ":ohflash(//build/toolchain/mingw:mingw_x86_64)" ] +} + +group("flashhost_target_standard_all") { + deps = [ + ":flashhost_target_standard_linux", + ":flashhost_target_standard_mingw", + ] +} + group("updater_flashd") { deps = [ ":libflashd" ] } diff --git a/services/flashd/common/flash_define.h b/services/flashd/common/flash_define.h new file mode 100755 index 0000000000000000000000000000000000000000..20361a07008c867b53f732674718022098684f8d --- /dev/null +++ b/services/flashd/common/flash_define.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef UPDATER_HDC_DEFINE_H +#define UPDATER_HDC_DEFINE_H +#include "common.h" + +namespace Hdc { +const string CMDSTR_UPDATE_SYSTEM = "update"; +const string CMDSTR_FLASH_PARTITION = "flash"; +const string CMDSTR_ERASE_PARTITION = "erase"; +const string CMDSTR_FORMAT_PARTITION = "format"; + +// update +const int CMD_UPDATER_UPDATE_INIT = CMD_APP_INIT + 200; +const int CMD_UPDATER_FLASH_INIT = CMD_UPDATER_UPDATE_INIT + 1; +const int CMD_UPDATER_CHECK = CMD_UPDATER_UPDATE_INIT + 2; +const int CMD_UPDATER_BEGIN = CMD_UPDATER_UPDATE_INIT + 3; +const int CMD_UPDATER_DATA = CMD_UPDATER_UPDATE_INIT + 4; +const int CMD_UPDATER_FINISH = CMD_UPDATER_UPDATE_INIT + 5; +const int CMD_UPDATER_ERASE = CMD_UPDATER_UPDATE_INIT + 6; +const int CMD_UPDATER_FORMAT = CMD_UPDATER_UPDATE_INIT + 7; +const int CMD_UPDATER_PROGRESS = CMD_UPDATER_UPDATE_INIT + 8; + +const int TASK_UPDATER = TASK_APP + 1; +} // namespace Hdc +#endif // UPDATER_HDC_DEFINE_H diff --git a/services/flashd/daemon/daemon.cpp b/services/flashd/daemon/daemon.cpp new file mode 100755 index 0000000000000000000000000000000000000000..fcf55dfa72a58bdbc03844e51202c5ee3a4943e5 --- /dev/null +++ b/services/flashd/daemon/daemon.cpp @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon.h" + +#include + +#include "daemon_updater.h" +#include "flash_define.h" +#include "serial_struct.h" + +namespace Hdc { +HdcDaemon::HdcDaemon(bool serverOrDaemonIn) + : HdcSessionBase(serverOrDaemonIn) +{ + clsTCPServ = nullptr; + clsUSBServ = nullptr; + clsJdwp = nullptr; + enableSecure = false; +} + +HdcDaemon::~HdcDaemon() +{ + WRITE_LOG(LOG_DEBUG, "~HdcDaemon"); +} + +void HdcDaemon::ClearInstanceResource() +{ + TryStopInstance(); + Base::TryCloseLoop(&loopMain, "HdcDaemon::~HdcDaemon"); + if (clsTCPServ) { + delete (HdcDaemonTCP *)clsTCPServ; + clsTCPServ = nullptr; + } + if (clsUSBServ) { + delete (HdcDaemonUSB *)clsUSBServ; + clsUSBServ = nullptr; + } + if (clsJdwp) { + delete (HdcJdwp *)clsJdwp; + clsJdwp = nullptr; + } + WRITE_LOG(LOG_DEBUG, "~HdcDaemon finish"); +} + +void HdcDaemon::TryStopInstance() +{ + ClearSessions(); + if (clsTCPServ) { + WRITE_LOG(LOG_DEBUG, "Stop TCP"); + ((HdcDaemonTCP *)clsTCPServ)->Stop(); + } + if (clsUSBServ) { + WRITE_LOG(LOG_DEBUG, "Stop USB"); + ((HdcDaemonUSB *)clsUSBServ)->Stop(); + } + ((HdcJdwp *)clsJdwp)->Stop(); + // workaround temply remove MainLoop instance clear + ReMainLoopForInstanceClear(); + WRITE_LOG(LOG_DEBUG, "Stop loopmain"); +} + +void HdcDaemon::InitMod(bool bEnableTCP, bool bEnableUSB) +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemon InitMod"); + if (bEnableTCP) { + // tcp + clsTCPServ = new HdcDaemonTCP(false, this); + ((HdcDaemonTCP *)clsTCPServ)->Initial(); + } + if (bEnableUSB) { + // usb + clsUSBServ = new HdcDaemonUSB(false, this); + ((HdcDaemonUSB *)clsUSBServ)->Initial(); + } + + clsJdwp = new HdcJdwp(&loopMain); + ((HdcJdwp *)clsJdwp)->Initial(); + + // enable security + char value[4] = "0"; + Base::GetHdcProperty("ro.hdc.secure", value, sizeof(value)); + string secure = value; + enableSecure = (Base::Trim(secure) == "1"); +} + +// clang-format off +#ifdef HDC_SUPPORT_FLASHD +bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + hTaskInfo->ownerSessionClass = this; + switch (command) { + case CMD_UNITY_REBOOT: + case CMD_UNITY_RUNMODE: + ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); + break; + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_CHECK: + case CMD_UPDATER_BEGIN: + case CMD_UPDATER_DATA: + case CMD_UPDATER_FINISH: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: + case CMD_UPDATER_PROGRESS: + ret = TaskCommandDispatch(hTaskInfo, TASK_UPDATER, command, payload, payloadSize); + break; + default: + std::string info = "Command not support in flashd\n"; + Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); + uint8_t count = 1; + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + break; + } + return ret; +} +#else +bool HdcDaemon::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +{ + std::string info = "Command not support in hdcd\n"; + Send(hSession->sessionId, channelId, CMD_KERNEL_ECHO_RAW, (uint8_t *)info.data(), info.size()); + uint8_t count = 1; + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + return true; +} +// clang-format on +#endif + +bool HdcDaemon::HandDaemonAuth(HSession hSession, const uint32_t channelId, SessionHandShake &handshake) +{ + bool ret = false; + switch (handshake.authType) { + case AUTH_NONE: { // AUTH_NONE -> AUTH + hSession->tokenRSA = Base::GetRandomString(SHA_DIGEST_LENGTH); + handshake.authType = AUTH_TOKEN; + handshake.buf = hSession->tokenRSA; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + case AUTH_SIGNATURE: { + // When Host is first connected to the device, the signature authentication is inevitable, and the + // certificate verification must be triggered. + // + // When the certificate is verified, the client sends a public key to the device, triggered the system UI + // jump out dialog, and click the system, the system will store the Host public key certificate in the + // device locally, and the signature authentication will be correct when the subsequent connection is + // connected. + if (!HdcAuth::AuthVerify((uint8_t *)hSession->tokenRSA.c_str(), (uint8_t *)handshake.buf.c_str(), + handshake.buf.size())) { + // Next auth + handshake.authType = AUTH_TOKEN; + handshake.buf = hSession->tokenRSA; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), + bufString.size()); + break; + } + ret = true; + break; + } + case AUTH_PUBLICKEY: { + ret = HdcAuth::PostUIConfirm(handshake.buf); + WRITE_LOG(LOG_DEBUG, "Auth host OK, postUIConfirm"); + break; + } + default: + break; + } + return ret; +} + +bool HdcDaemon::DaemonSessionHandshake(HSession hSession, const uint32_t channelId, uint8_t *payload, int payloadSize) +{ + // session handshake step2 + string s = string((char *)payload, payloadSize); + SessionHandShake handshake; + string err; + SerialStruct::ParseFromString(handshake, s); + // banner to check is parse ok... + if (handshake.banner != HANDSHAKE_MESSAGE) { + hSession->availTailIndex = 0; + WRITE_LOG(LOG_FATAL, "Recv server-hello failed"); + return false; + } + if (handshake.authType == AUTH_NONE) { + // daemon handshake 1st packet + uint32_t unOld = hSession->sessionId; + hSession->sessionId = handshake.sessionId; + hSession->connectKey = handshake.connectKey; + AdminSession(OP_UPDATE, unOld, hSession); + if (clsUSBServ != nullptr) { + (reinterpret_cast(clsUSBServ))->OnNewHandshakeOK(hSession->sessionId); + } + + handshake.sessionId = 0; + handshake.connectKey = ""; + } + if (enableSecure && !HandDaemonAuth(hSession, channelId, handshake)) { + return false; + } + // handshake auth OK.Can append the sending device information to HOST + char hostName[BUF_SIZE_MEDIUM] = ""; + size_t len = sizeof(hostName); + uv_os_gethostname(hostName, &len); + handshake.authType = AUTH_OK; + handshake.buf = hostName; + string bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, channelId, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + hSession->handshakeOK = true; + return true; +} + +bool HdcDaemon::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + int payloadSize) +{ + bool ret = true; + if (!hSession->handshakeOK && command != CMD_KERNEL_HANDSHAKE) { + ret = false; + return ret; + } + switch (command) { + case CMD_KERNEL_HANDSHAKE: { + // session handshake step2 + ret = DaemonSessionHandshake(hSession, channelId, payload, payloadSize); + break; + } + case CMD_KERNEL_CHANNEL_CLOSE: { // Daemon is only cleaning up the Channel task + ClearOwnTasks(hSession, channelId); + if (*payload == 1) { + --(*payload); + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + } + ret = true; + break; + } + default: + ret = DispatchTaskData(hSession, channelId, command, payload, payloadSize); + break; + } + return ret; +} + +bool HdcDaemon::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) +{ + bool ret = true; + switch (hTask->taskType) { + case TYPE_UNITY: + ret = DoTaskRemove(hTask, op); + break; + case TYPE_SHELL: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FILE: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FORWARD: + ret = DoTaskRemove(hTask, op); + break; + case TASK_APP: + ret = DoTaskRemove(hTask, op); + break; +#ifdef HDC_SUPPORT_FLASHD + case TASK_UPDATER: + ret = DoTaskRemove(hTask, op); + break; +#endif + default: + ret = false; + break; + } + return ret; +} + +bool HdcDaemon::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, + uint8_t *bufPtr, const int size) +{ + return Send(sessionId, channelId, command, (uint8_t *)bufPtr, size) > 0; +} + +void HdcDaemon::JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) +{ + uint32_t pid = *(uint32_t *)(buf + 1); + uint32_t fd = *(uint32_t *)(buf + 5); // 5 : fd offset + ((HdcJdwp *)clsJdwp)->SendJdwpNewFD(pid, fd); +}; +} // namespace Hdc diff --git a/services/flashd/daemon/daemon_unity.cpp b/services/flashd/daemon/daemon_unity.cpp new file mode 100755 index 0000000000000000000000000000000000000000..cbe178065d03c13138f5ee1aa00fa2086601df98 --- /dev/null +++ b/services/flashd/daemon/daemon_unity.cpp @@ -0,0 +1,303 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "daemon_unity.h" +#include +#ifdef __MUSL__ +#include "init_reboot.h" +#endif + +namespace Hdc { +HdcDaemonUnity::HdcDaemonUnity(HTaskInfo hTaskInfo) + : HdcTaskBase(hTaskInfo) +{ + currentDataCommand = CMD_KERNEL_ECHO_RAW; // Default output to shelldata +} + +HdcDaemonUnity::~HdcDaemonUnity() +{ + WRITE_LOG(LOG_DEBUG, "HdcDaemonUnity::~HdcDaemonUnity finish"); +} + +void HdcDaemonUnity::StopTask() +{ + asyncCommand.DoRelease(); +}; + +bool HdcDaemonUnity::ReadyForRelease() +{ + if (!HdcTaskBase::ReadyForRelease() || !asyncCommand.ReadyForRelease()) { + return false; + } + return true; +} + +bool HdcDaemonUnity::AsyncCmdOut(bool finish, int64_t exitStatus, const string result) +{ +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/execute.result").c_str(), (uint8_t *)result.c_str(), result.size(), + countUt++ == 0); +#endif + bool ret = false; + bool wantFinish = false; + do { + if (finish) { + wantFinish = true; + ret = true; + --refCount; + break; + } + if (!SendToAnother(currentDataCommand, (uint8_t *)result.c_str(), result.size())) { + break; + } + ret = true; + } while (false); + if (wantFinish) { + TaskFinish(); + } + return ret; +} + +int HdcDaemonUnity::ExecuteShell(const char *shellCommand) +{ + do { + AsyncCmd::CmdResultCallback funcResultOutput; + funcResultOutput = std::bind(&HdcDaemonUnity::AsyncCmdOut, this, std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3); + if (!asyncCommand.Initial(loopTask, funcResultOutput, + asyncCommand.GetDefaultOption() | asyncCommand.OPTION_READBACK_OUT)) { + break; + } + asyncCommand.ExecuteCommand(shellCommand); + ++refCount; + return RET_SUCCESS; + } while (false); + + TaskFinish(); + WRITE_LOG(LOG_DEBUG, "Shell failed finish"); + return -1; +} + +bool HdcDaemonUnity::FindMountDeviceByPath(const char *toQuery, char *dev) +{ + int fd; + int res; + char *token = nullptr; + const char delims[] = "\n"; + char buf[BUF_SIZE_DEFAULT2]; + + fd = open("/proc/mounts", O_RDONLY | O_CLOEXEC); + if (fd < 0) { + return false; + } + read(fd, buf, sizeof(buf) - 1); + close(fd); + buf[sizeof(buf) - 1] = '\0'; + token = strtok(buf, delims); + + while (token) { + char dir[BUF_SIZE_SMALL] = ""; + int freq; + int passnno; + // clang-format off + res = sscanf_s(token, "%255s %255s %*s %*s %d %d\n", dev, BUF_SIZE_SMALL - 1, + dir, BUF_SIZE_SMALL - 1, &freq, &passnno); + // clang-format on + dev[BUF_SIZE_SMALL - 1] = '\0'; + dir[BUF_SIZE_SMALL - 1] = '\0'; + if (res == 4 && (strcmp(toQuery, dir) == 0)) { // 4 : The correct number of parameters + return true; + } + token = strtok(nullptr, delims); + } + return false; +} + +bool HdcDaemonUnity::RemountPartition(const char *dir) +{ + int fd; + int off = 0; + char dev[BUF_SIZE_SMALL] = ""; + + if (!FindMountDeviceByPath(dir, dev) || strlen(dev) < 4) { // 4 : file count + WRITE_LOG(LOG_DEBUG, "FindMountDeviceByPath failed"); + return false; + } + + if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) { + WRITE_LOG(LOG_DEBUG, "Open device:%s failed, error:%d", dev, errno); + return false; + } + ioctl(fd, BLKROSET, &off); + close(fd); + + if (mount(dev, dir, "none", MS_REMOUNT, nullptr) < 0) { + WRITE_LOG(LOG_DEBUG, "Mount device failed"); + return false; + } + return true; +} + +bool HdcDaemonUnity::RemountDevice() +{ + if (getuid() != 0) { + LogMsg(MSG_FAIL, "Opearte need running as root"); + return false; + } + struct stat info; + if (!lstat("/vendor", &info) && (info.st_mode & S_IFMT) == S_IFDIR) { + // has vendor + if (!RemountPartition("/vendor")) { + LogMsg(MSG_FAIL, "Mount failed"); + return false; + } + } + if (!lstat("/data", &info) && (info.st_mode & S_IFMT) == S_IFDIR) { + if (!RemountPartition("/data")) { + return false; + } + } + LogMsg(MSG_OK, "Mount finish"); + return true; +} + +bool HdcDaemonUnity::RebootDevice(const string &cmd) +{ + sync(); +#ifndef __MUSL__ + string propertyVal; + if (!cmd.size()) { + propertyVal = "reboot"; + } else { + propertyVal = Base::StringFormat("reboot,%s", cmd.c_str()); + } + return Base::SetHdcProperty(rebootProperty.c_str(), propertyVal.c_str()); +#else + string reason; + if (cmd == "recovery") { + reason = "updater"; + } else if (cmd == "bootloader") { + reason = "NoArgument"; + } else { + reason = cmd; + } + return DoReboot(reason.c_str()); +#endif +} + +bool HdcDaemonUnity::SetDeviceRunMode(void *daemonIn, const char *cmd) +{ + HdcDaemon *daemon = (HdcDaemon *)daemonIn; + WRITE_LOG(LOG_DEBUG, "Set run mode:%s", cmd); + if (!strcmp(CMDSTR_TMODE_USB.c_str(), cmd)) { + Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_USB.c_str()); + } else if (!strncmp("port", cmd, strlen("port"))) { + Base::SetHdcProperty("persist.hdc.mode", CMDSTR_TMODE_TCP.c_str()); + if (!strncmp("port ", cmd, strlen("port "))) { + const char *port = cmd + 5; + Base::SetHdcProperty("persist.hdc.port", port); + } + } else { + LogMsg(MSG_FAIL, "Unknow command"); + return false; + } + // shutdown + daemon->PostStopInstanceMessage(true); + LogMsg(MSG_OK, "Set device run mode successful."); + return true; +} + +inline bool HdcDaemonUnity::GetHiLog(const char *cmd) +{ + string cmdDo = "hilog"; + if (cmd && !strcmp((char *)cmd, "v")) { + cmdDo += " -v long"; + } + ExecuteShell(cmdDo.c_str()); + return true; +} + +inline bool HdcDaemonUnity::ListJdwpProcess(void *daemonIn) +{ + HdcDaemon *daemon = (HdcDaemon *)daemonIn; + string result = ((HdcJdwp *)daemon->clsJdwp)->GetProcessList(); + if (!result.size()) { + result = EMPTY_ECHO; + } else { + result.erase(result.end() - 1); // remove tail \n + } + LogMsg(MSG_OK, result.c_str()); + return true; +} + +bool HdcDaemonUnity::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + bool ret = true; + HdcDaemon *daemon = (HdcDaemon *)taskInfo->ownerSessionClass; + // Both are not executed, do not need to be detected 'childReady' + string strPayload = string((char *)payload, payloadSize); + switch (command) { + case CMD_UNITY_EXECUTE: { + ExecuteShell((char *)strPayload.c_str()); + break; + } + case CMD_UNITY_REMOUNT: { + ret = false; + RemountDevice(); + break; + } + case CMD_UNITY_REBOOT: { + ret = false; + RebootDevice(strPayload); + break; + } + case CMD_UNITY_RUNMODE: { + ret = false; + SetDeviceRunMode(daemon, strPayload.c_str()); + break; + } + case CMD_UNITY_HILOG: { + GetHiLog(strPayload.c_str()); + break; + } + case CMD_UNITY_ROOTRUN: { + ret = false; + if (payloadSize != 0 && !strcmp((char *)strPayload.c_str(), "r")) { + Base::SetHdcProperty("persist.hdc.root", "0"); + } else { + Base::SetHdcProperty("persist.hdc.root", "1"); + } + daemon->PostStopInstanceMessage(true); + break; + } + case CMD_UNITY_TERMINATE: { + daemon->PostStopInstanceMessage(!strcmp((char *)strPayload.c_str(), "1")); + break; + } + case CMD_UNITY_BUGREPORT_INIT: { + currentDataCommand = CMD_UNITY_BUGREPORT_DATA; + ExecuteShell((char *)CMDSTR_BUGREPORT.c_str()); + break; + } + case CMD_UNITY_JPID: { + ret = false; + ListJdwpProcess(daemon); + break; + } + default: + break; + } + return ret; +}; +} // namespace Hdc diff --git a/services/flashd/daemon/daemon_updater.cpp b/services/flashd/daemon/daemon_updater.cpp index 37dae05c03b6db2900d644c9b062f2d8243e8ed1..2e84fe7547ed01099416bcb841f77d4a9692df39 100755 --- a/services/flashd/daemon/daemon_updater.cpp +++ b/services/flashd/daemon/daemon_updater.cpp @@ -16,6 +16,7 @@ #include "daemon_common.h" #include "flashd/flashd.h" #include "flash_utils.h" +#include "flash_define.h" namespace Hdc { DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) @@ -29,14 +30,6 @@ DaemonUpdater::~DaemonUpdater() WRITE_LOG(LOG_DEBUG, "~DaemonUpdater refCount %d", refCount); } -bool DaemonUpdater::ReadyForRelease() -{ - if (!HdcTaskBase::ReadyForRelease()) { - return false; - } - return true; -} - bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) { #ifndef UPDATER_UT @@ -49,15 +42,18 @@ bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, co [&](uint32_t type, size_t dataLen, const void *context) { SendProgress(dataLen); }); - if (ret != 0) { - return false; - } + FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(command, -1, errorMsg_); + return false, "Faild to create flashd"); } switch (command) { case CMD_UPDATER_DATA: { + const uint8_t payloadPrefixReserve = 64; string serialStrring((char *)payload, payloadPrefixReserve); - TransferPayload pld; + TransferPayload pld {}; SerialStruct::ParseFromString(pld, serialStrring); +#ifdef UPDATER_UT + pld.uncompressSize = pld.compressSize; +#endif SendProgress(pld.uncompressSize); break; } @@ -88,9 +84,7 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload { uint64_t realSize = 0; int ret = memcpy_s(&realSize, sizeof(realSize), payload, sizeof(realSize)); - if (ret != 0) { - return; - } + FLASHDAEMON_CHECK(ret == 0, return, "Faild to memcpy"); string bufString((char *)payload + sizeof(realSize), payloadSize - sizeof(realSize)); SerialStruct::ParseFromString(ctxNow.transferConfig, bufString); ctxNow.master = false; @@ -117,6 +111,7 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload } else { WRITE_LOG(LOG_FATAL, "ProcessUpdateCheck local function %s size %lu realSize %lu", ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize); + AsyncUpdateFinish(type, -1, "Invalid command"); return; } ctxNow.localPath = ctxNow.transferConfig.optionalName; @@ -124,34 +119,31 @@ void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payload if (ret == 0) { refCount++; WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck localPath %s", ctxNow.localPath.c_str()); +#ifndef UPDATER_UT uv_fs_open(loopTask, &ctxNow.fsOpenReq, ctxNow.localPath.c_str(), UV_FS_O_TRUNC | UV_FS_O_CREAT | UV_FS_O_WRONLY, S_IRUSR, OnFileOpen); - } else { - AsyncUpdateFinish(type, ret, errorMsg_); +#endif } + FLASHDAEMON_CHECK(ret == 0, AsyncUpdateFinish(type, ret, errorMsg_), "Faild to prepare for %d", type); } void DaemonUpdater::RunUpdateShell(uint8_t type, const std::string &options, const std::string &package) { int ret = flashd::DoUpdaterFlash(flashHandle_, type, options, package); - if (ret != 0) { - WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); - } AsyncUpdateFinish(type, ret, errorMsg_); } void DaemonUpdater::SendProgress(size_t dataLen) { currSize_ += dataLen; - int32_t percentage = (int32_t)(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_); - if (percentage >= flashd::PERCENT_FINISH) { + int32_t percentage = static_cast(currSize_ * (flashd::PERCENT_FINISH - 1) / totalSize_); + if (static_cast(percentage) >= flashd::PERCENT_FINISH) { WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage %d", currSize_, percentage); return; } if (percentage_ < percentage) { percentage_ = percentage; WRITE_LOG(LOG_DEBUG, "SendProgress %lf percentage_ %d", currSize_, percentage_); - FLASHING_LOGI("SendProgress %lf percentage_ %d", currSize_, percentage_); SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); } } @@ -172,24 +164,21 @@ void DaemonUpdater::WhenTransferFinish(CtxFile *context) type = flashd::UPDATEMOD_FLASH; } AsyncUpdateFinish(type, ret, errorMsg_); - ret = flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath); - if (ret != 0) { - WRITE_LOG(LOG_FATAL, errorMsg_.c_str()); - } TaskFinish(); } -void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result) +void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result) { - WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish ret %d result %s", ret, result.c_str()); - uint32_t percentage = (ret != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH; + WRITE_LOG(LOG_DEBUG, "AsyncUpdateFinish retCode %d result %s", retCode, result.c_str()); + uint32_t percentage = (retCode != 0) ? flashd::PERCENT_CLEAR : flashd::PERCENT_FINISH; SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); + (void)flashd::DoUpdaterFinish(flashHandle_, type, ctxNow.localPath); string echo = result; echo = Base::ReplaceAll(echo, "\n", " "); vector vecBuf; vecBuf.push_back(type); - if (ret != 0) { + if (retCode != 0) { vecBuf.push_back(MSG_FAIL); } else { vecBuf.push_back(MSG_OK); diff --git a/services/flashd/daemon/daemon_updater.h b/services/flashd/daemon/daemon_updater.h index a7e35b67b731348e516e0101c724456d5a8c11c6..6f7bb76f8ee027b05874600cd80e227ef1068bca 100755 --- a/services/flashd/daemon/daemon_updater.h +++ b/services/flashd/daemon/daemon_updater.h @@ -20,12 +20,17 @@ #include "transfer.h" namespace Hdc { +#define FLASHDAEMON_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + WRITE_LOG(LOG_FATAL, __VA_ARGS__); \ + exper; \ + } + class DaemonUpdater : public HdcTransferBase { public: explicit DaemonUpdater(HTaskInfo hTaskInfo); virtual ~DaemonUpdater(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; - bool ReadyForRelease(); #ifdef UPDATER_UT void DoTransferFinish(); #endif @@ -33,7 +38,7 @@ private: virtual void WhenTransferFinish(CtxFile *context) override; void ProcessUpdateCheck(const uint8_t *payload, const int payloadSize); void RunUpdateShell(uint8_t type, const std::string &options, const std::string &package); - void AsyncUpdateFinish(uint8_t type, int32_t ret, const string &result); + void AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result); void SendProgress(size_t dataLen); #ifdef UPDATER_UT bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) diff --git a/services/flashd/daemon/flashd_main.cpp b/services/flashd/daemon/flashd_main.cpp index 5d73fd8f4c52094d3b138f0d28b7c46026bbd983..f5270bc28a0dab5f553e13f636aeda3c7b60c1e2 100755 --- a/services/flashd/daemon/flashd_main.cpp +++ b/services/flashd/daemon/flashd_main.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "daemon_common.h" +#include "daemon_updater.h" #include "flashd/flashd.h" #include "updater/updater.h" @@ -24,15 +25,18 @@ int flashd_main(int argc, char **argv) std::vector args = updater::ParseParams(argc, argv); bool enableUsb = false; bool enableTcp = false; + WRITE_LOG(LOG_DEBUG, "flashd main run %d", argc); + const int size = 64; + char modeSet[size] = ""; + Base::GetHdcProperty("persist.hdc.mode", modeSet, size); + WRITE_LOG(LOG_DEBUG, "Background mode, persist.hdc.mode %s", modeSet); for (std::string arg : args) { if (arg.find("-l") != std::string::npos) { int logLevel = atoi(arg.c_str() + strlen("-l")); - if (logLevel < 0 || logLevel > LOG_LAST) { - WRITE_LOG(LOG_DEBUG, "Loglevel error!\n"); - return -1; - } + FLASHDAEMON_CHECK(!(logLevel < 0 || logLevel > LOG_LAST), + logLevel = LOG_LAST, "Loglevel error %d", logLevel); Base::SetLogLevel(logLevel); - } else if (arg.find("-t") != std::string::npos) { + } else if (arg.find("-t") != std::string::npos || strncmp(modeSet, "tcp", 3) == 0) { // 3 tcp enableTcp = true; } else if (arg.find("-u") != std::string::npos) { enableUsb = true; @@ -43,8 +47,6 @@ int flashd_main(int argc, char **argv) Base::PrintMessage("Both TCP and USB are disable, default enable usb"); enableUsb = true; } - - WRITE_LOG(LOG_DEBUG, "flashd main run"); HdcDaemon daemon(false); daemon.InitMod(enableTcp, enableUsb); #ifndef UPDATER_UT diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp index 1cd136b58c8b63b3e589d93d35705d6ed6c2f3f3..c5050ba034746eafbf9b474dd8aa31f01b8e225f 100755 --- a/services/flashd/flash_service.cpp +++ b/services/flashd/flash_service.cpp @@ -38,6 +38,7 @@ using namespace hpackage; using namespace updater; namespace flashd { +static std::atomic g_flashdRunning { false }; FlashService::~FlashService() { for (auto part : partitions_) { @@ -84,7 +85,12 @@ int FlashService::DoUpdate(const std::string &packageName) FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); RecordMsg(updater::ERROR, "Can not load package %s", packageName.c_str()); return FLASHING_PACKAGE_INVALID, "Failed to load package %s", packageName.c_str()); -#ifndef LOCAL_SUPPORT + + ret = UpdatePreProcess(pkgManager, packageName); + FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); + RecordMsg(updater::ERROR, "Invalid package %s", packageName.c_str()); + return FLASHING_PACKAGE_INVALID, "Invalid package %s", packageName.c_str()); +#ifndef UPDATER_UT ret = updater::ExecUpdate(pkgManager, 0, [&](const char *cmd, const char *content) { if (strncmp(cmd, "data", strlen(cmd)) == 0) { @@ -93,6 +99,9 @@ int FlashService::DoUpdate(const std::string &packageName) } }); #endif + FLASHING_CHECK(ret == PKG_SUCCESS, PkgManager::ReleasePackageInstance(pkgManager); + RecordMsg(updater::ERROR, "Failed to update package %s", packageName.c_str()); + return FLASHING_PACKAGE_INVALID, "Failed to update package %s", packageName.c_str()); FLASHING_LOGI("Load packageName %s success %llu", packageName.c_str(), pkgLen); PkgManager::ReleasePackageInstance(pkgManager); return ret; @@ -205,7 +214,7 @@ PartitionPtr FlashService::GetPartition(const std::string &partition) const { const std::string partName = GetPartNameByAlias(partition); for (auto part : partitions_) { - if (partName.compare(part->GetPartitionName()) == 0) { + if (strcmp(partName.c_str(), part->GetPartitionName().c_str()) == 0) { return part; } } @@ -227,7 +236,7 @@ int FlashService::LoadBlockDevice(const std::string &fileDir) continue; } std::string devPath = fileDir + "/" + entry->d_name; - if (entry->d_type == 10) { // 10 link 文件 + if (entry->d_type == 10) { // 10 link file readlink(devPath.c_str(), buffer.data(), DEVICE_PATH_SIZE); devPath = fileDir + "/" + buffer.data(); memset_s(buffer.data(), DEVICE_PATH_SIZE, 0, DEVICE_PATH_SIZE); @@ -241,13 +250,13 @@ int FlashService::LoadBlockDevice(const std::string &fileDir) } ret = 0; if (SCSI_BLK_MAJOR(devMajor)) { - if ((devMinor % 0x10) == 0) { + if ((devMinor % 0x10) == 0) { // 0x10 scsi device ret = AddNewBlockDevice(DeviceType::DEVICE_SCSI, devPath); } else { partitionsName.push_back(devPath); } } else if (devMajor == SDMMC_MAJOR) { - if (devMinor % 0x08 == 0) { + if (devMinor % 0x08 == 0) { // 0x08 emmc ret = AddNewBlockDevice(DeviceType::DEVICE_EMMC, devPath); } else { partitionsName.push_back(devPath); @@ -343,19 +352,20 @@ int FlashService::ExecCommand(const std::vector &cmds) } extractedCmds.push_back(nullptr); pid_t pid = fork(); - if (pid < 0) { - FLASHING_CHECK(0, return -1, "Failed to fork %d error:%d", pid, errno); - return errno; - } if (pid == 0) { +#ifndef UPDATER_UT execv(extractedCmds[0], extractedCmds.data()); +#endif exit(0x7f); // 0x7f exit code } + FLASHING_CHECK(pid > 0, return -1, "Failed to fork %d error:%d", pid, errno); +#ifndef UPDATER_UT int status; waitpid(pid, &status, 0); if (WEXITSTATUS(status) != 0 || !WIFEXITED(status)) { return WEXITSTATUS(status); } +#endif return 0; } @@ -381,9 +391,7 @@ void FlashService::PostProgress(uint32_t type, size_t dataLen, const void *conte int FlashService::CheckOperationPermission(int type, const std::string &partition) const { - if (type >= UPDATEMOD_MAX) { - return 1; - } + FLASHING_CHECK(type < UPDATEMOD_MAX, return 1, "Invalid type %d", type); std::vector forbitPartName[] = { {}, // updater {"updater"}, // flash @@ -423,7 +431,7 @@ const std::string FlashService::GetPartNameByAlias(const std::string &alias) }; for (auto iter = partNameMap.begin(); iter != partNameMap.end(); iter++) { for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); iter2++) { - if (*iter2 == alias) { + if (strcmp(alias.c_str(), (*iter2).c_str()) == 0) { return iter->first; } } @@ -453,7 +461,7 @@ static std::string GetValueFromParam(const std::vector ¶ms, { std::string ret = defValue; for (size_t i = 0; i < params.size(); i++) { - if (paramType.compare(params[i]) == 0) { + if (strcmp(paramType.c_str(), params[i].c_str()) == 0) { if (i < (params.size() - 1)) { ret = params[i + 1]; } else { @@ -468,7 +476,7 @@ static bool FilterParam(const std::string ¶m, const std::vector { auto iter = filter.begin(); while (iter != filter.end()) { - if (param.compare(*iter) == 0) { + if (strcmp(param.c_str(), (*iter).c_str()) == 0) { return true; } iter++; @@ -511,13 +519,19 @@ static int GetCmdParam(uint8_t type, const std::string &origString, int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor) { + int mode = BOOT_UPDATER; + int ret = updater::GetBootMode(mode); + FLASHING_CHECK(ret == 0 && mode == BOOT_FLASHD, errorMsg = "Boot mode is not in flashd"; + return FLASHING_SYSTEM_ERROR, "Boot mode error"); + + FLASHING_CHECK(!g_flashdRunning, errorMsg = "Flashd has been running"; + return FLASHING_SYSTEM_ERROR, "Flashd has been running"); + g_flashdRunning = true; + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle"); flashd::FlashService *flash = new flashd::FlashService(errorMsg, progressor); - if (flash == nullptr) { - FLASHING_LOGE("Failed to create flash service"); - errorMsg = "Create instance fail"; - return FLASHING_SYSTEM_ERROR; - } + FLASHING_CHECK(flash != nullptr, errorMsg = "Failed to create flash service"; + return FLASHING_SYSTEM_ERROR, "Failed to create flash service"); *handle = static_cast(flash); return 0; } @@ -538,12 +552,13 @@ int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdPar // 检查剩余分区大小,扩展分区 const std::string root = flashd::FlashService::GetPathRoot(FLASHD_FILE_PATH); ret = MountForPath(root); - FLASHING_CHECK(ret == 0, + FLASHING_CHECK(ret == 0, g_flashdRunning = false; flash->RecordMsg(updater::ERROR, "Failed to mount data paratition for %s", filePath.c_str()); return FLASHING_INVALID_SPACE, "Failed to mount data paratition for %s", filePath.c_str()); ret = flash->DoResizeParatiton(root, MIN_BLOCKS_FOR_UPDATE); - FLASHING_CHECK(ret == 0, return ret, "Failed to resize partition"); + FLASHING_CHECK(ret == 0, g_flashdRunning = false; + return ret, "Failed to resize partition"); if (access(FLASHD_FILE_PATH.c_str(), F_OK) == -1) { mkdir(FLASHD_FILE_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } @@ -567,23 +582,24 @@ int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam std::vector params {}; int ret = GetCmdParam(type, cmdParam, {"-f"}, params); - FLASHING_CHECK(ret == 0, + FLASHING_CHECK(ret == 0, g_flashdRunning = false; flash->RecordMsg(updater::ERROR, "Invalid param for %d", type); return FLASHING_ARG_INVALID, "Invalid param for %d", type); FLASHING_DEBUG("DoUpdaterFlash type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str()); switch (type) { case flashd::UPDATEMOD_UPDATE: { ret = flash->DoUpdate(filePath); - unlink(filePath.c_str()); break; } case flashd::UPDATEMOD_ERASE: - FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for erase"); + FLASHING_CHECK(params.size() > 1, g_flashdRunning = false; + return FLASHING_ARG_INVALID, "Invalid param size for erase"); ret = flash->DoErasePartition(params[1]); break; case flashd::UPDATEMOD_FORMAT: { std::string fsType = GetValueFromParam(params, "-t", "ext4"); - FLASHING_CHECK(params.size() > 1, return FLASHING_ARG_INVALID, "Invalid param size for format"); + FLASHING_CHECK(params.size() > 1, g_flashdRunning = false; + return FLASHING_ARG_INVALID, "Invalid param size for format"); ret = flash->DoFormatPartition(params[1], fsType); break; } @@ -598,15 +614,32 @@ int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partiti { FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); FLASHING_DEBUG("DoUpdaterFinish type: %d %s", type, partition.c_str()); - updater::PostUpdater(); switch (type) { case flashd::UPDATEMOD_UPDATE: { +#ifndef UPDATER_UT + unlink(partition.c_str()); +#endif + updater::PostUpdater(true); utils::DoReboot(""); break; } + case flashd::UPDATEMOD_FLASH: { + updater::PostUpdater(false); + break; + } default: break; } + g_flashdRunning = false; + return 0; +} + +int SetParameter(const char *key, const char *value) +{ + std::string sKey = key; + std::string sValue = value; + std::string sBuf = "param set " + sKey + " " + value; + system(sBuf.c_str()); return 0; } } // namespace flashd diff --git a/services/flashd/host/client.cpp b/services/flashd/host/client.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b2877c6b1560d40deb9f9cb5e64037ef87d4b53c --- /dev/null +++ b/services/flashd/host/client.cpp @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "client.h" + +#include "host_updater.h" +#include "server.h" + +namespace Hdc { +bool terminalStateChange = false; +HdcClient::HdcClient(const bool serverOrClient, const string &addrString, uv_loop_t *loopMainIn) + : HdcChannelBase(serverOrClient, addrString, loopMainIn) +{ + MallocChannel(&channel); // free by logic + debugRetryCount = 0; +} + +HdcClient::~HdcClient() +{ +#ifndef _WIN32 + if (terminalStateChange) { + tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); + } +#endif + Base::TryCloseLoop(loopMain, "ExecuteCommand finish"); +} + +void HdcClient::NotifyInstanceChannelFree(HChannel hChannel) +{ + if (bShellInteractive) { + WRITE_LOG(LOG_DEBUG, "Restore tty"); + ModifyTty(false, &hChannel->stdinTty); + } +} + +uint32_t HdcClient::GetLastPID() +{ + char bufPath[BUF_SIZE_MEDIUM] = ""; + size_t size = BUF_SIZE_MEDIUM; + char pidBuf[BUF_SIZE_TINY] = ""; + // get running pid to kill it + if (uv_os_tmpdir(bufPath, &size) < 0) { + WRITE_LOG(LOG_FATAL, "Tmppath failed"); + return 0; + } + string path = Base::StringFormat("%s%c.%s.pid", bufPath, Base::GetPathSep(), SERVER_NAME.c_str()); + Base::ReadBinFile(path.c_str(), (void **)&pidBuf, BUF_SIZE_TINY); + int pid = atoi(pidBuf); // pid maybe 0 + return pid; +} + +bool HdcClient::StartKillServer(const char *cmd, bool startOrKill) +{ + bool isNowRunning = Base::ProgramMutex(SERVER_NAME.c_str(), true) != 0; + const int SIGN_NUM = 9; + uint32_t pid = GetLastPID(); + if (!pid) { + return false; + } + if (startOrKill) { + if (isNowRunning) { + // already running + if (!strstr(cmd, " -r")) { + return true; + } + if (pid) { + uv_kill(pid, SIGN_NUM); + } + } + HdcServer::PullupServer(channelHostPort.c_str()); + } else { + if (isNowRunning && pid) { + uv_kill(pid, SIGN_NUM); + Base::PrintMessage("Kill server finish"); + } + // already running + if (!strstr(cmd, " -r")) { + return true; + } + HdcServer::PullupServer(channelHostPort.c_str()); + } + return true; +} + +void HdcClient::DoCtrlServiceWork(uv_check_t *handle) +{ + HdcClient *thisClass = (HdcClient *)handle->data; + const char *cmd = thisClass->command.c_str(); + string &strCmd = thisClass->command; + while (true) { + if (!strncmp(cmd, CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size())) { + thisClass->StartKillServer(cmd, true); + } else if (!strncmp(cmd, CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size())) { + thisClass->StartKillServer(cmd, false); + // clang-format off + } else if (!strncmp(cmd, CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size()) && + strCmd.find(" ") != std::string::npos) { + // clang-format on + string keyPath = strCmd.substr(CMDSTR_GENERATE_KEY.size() + 1, strCmd.size()); + HdcAuth::GenerateKey(keyPath.c_str()); + } else { + Base::PrintMessage("Unknow command"); + } + break; + } + Base::TryCloseHandle((const uv_handle_t *)handle); +} + +int HdcClient::CtrlServiceWork(const char *commandIn) +{ + command = commandIn; + ctrlServerWork.data = this; + uv_check_init(loopMain, &ctrlServerWork); + uv_check_start(&ctrlServerWork, DoCtrlServiceWork); + uv_run(loopMain, UV_RUN_NOWAIT); + return 0; +} + +string HdcClient::AutoConnectKey(string &doCommand, const string &preConnectKey) const +{ + string key = preConnectKey; + bool isNoTargetCommand = false; + vector vecNoConnectKeyCommand; + vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_VERSION); + vecNoConnectKeyCommand.push_back(CMDSTR_SOFTWARE_HELP); + vecNoConnectKeyCommand.push_back(CMDSTR_TARGET_DISCOVER); + vecNoConnectKeyCommand.push_back(CMDSTR_LIST_TARGETS); + vecNoConnectKeyCommand.push_back(CMDSTR_CONNECT_TARGET); + vecNoConnectKeyCommand.push_back(CMDSTR_KILL_SERVER); + vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " ls"); + vecNoConnectKeyCommand.push_back(CMDSTR_FORWARD_FPORT + " rm"); + for (string v : vecNoConnectKeyCommand) { + if (!doCommand.compare(0, v.size(), v)) { + isNoTargetCommand = true; + break; + } + } + if (isNoTargetCommand) { + key = ""; + } else { + if (!preConnectKey.size()) { + key = CMDSTR_CONNECT_ANY; + } + } + return key; +} + +int HdcClient::ExecuteCommand(const string &commandIn) +{ + char ip[BUF_SIZE_TINY] = ""; + uint16_t port = 0; + if (Base::ConnectKey2IPPort(channelHostPort.c_str(), ip, &port) < 0) { + return -1; + } + command = commandIn; + connectKey = AutoConnectKey(command, connectKey); + ConnectServerForClient(ip, port); + uv_timer_init(loopMain, &waitTimeDoCmd); + waitTimeDoCmd.data = this; + uv_timer_start(&waitTimeDoCmd, CommandWorker, 10, 10); // 10 10 repeat + WorkerPendding(); + return 0; +} + +int HdcClient::Initial(const string &connectKeyIn) +{ + connectKey = connectKeyIn; + if (!channelHostPort.size() || !channelHost.size() || !channelPort) { + WRITE_LOG(LOG_FATAL, "Listen string initial failed"); + return ERR_PARM_FAIL; + } + return 0; +} + +int HdcClient::ConnectServerForClient(const char *ip, uint16_t port) +{ + if (uv_is_closing((const uv_handle_t *)&channel->hWorkTCP)) { + return ERR_SOCKET_FAIL; + } + WRITE_LOG(LOG_DEBUG, "Try to connect %s:%d", ip, port); + struct sockaddr_in dest; + uv_ip4_addr(ip, port, &dest); + uv_connect_t *conn = new uv_connect_t(); + conn->data = this; + uv_tcp_connect(conn, (uv_tcp_t *)&channel->hWorkTCP, (const struct sockaddr *)&dest, Connect); + return 0; +} + +void HdcClient::CommandWorker(uv_timer_t *handle) +{ + const uint16_t maxWaitRetry = 500; + HdcClient *thisClass = (HdcClient *)handle->data; + if (++thisClass->debugRetryCount > maxWaitRetry) { + uv_timer_stop(handle); + uv_stop(thisClass->loopMain); + WRITE_LOG(LOG_DEBUG, "Connect server failed"); + return; + } + if (!thisClass->channel->handshakeOK) { + return; + } + uv_timer_stop(handle); + WRITE_LOG(LOG_DEBUG, "Connect server successful"); + bool closeInput = false; + if (!HostUpdater::ConfirmCommand(thisClass->command, closeInput)) { + uv_timer_stop(handle); + uv_stop(thisClass->loopMain); + WRITE_LOG(LOG_DEBUG, "Cmd \'%s\' has been canceld", thisClass->command.c_str()); + return; + } + while (closeInput) { +#ifndef _WIN32 + if (tcgetattr(STDIN_FILENO, &thisClass->terminalState)) { + break; + } + termios tio; + if (tcgetattr(STDIN_FILENO, &tio)) { + break; + } + cfmakeraw(&tio); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); + terminalStateChange = true; +#endif + break; + } + thisClass->Send(thisClass->channel->channelId, (uint8_t *)thisClass->command.c_str(), + thisClass->command.size() + 1); +} + +void HdcClient::AllocStdbuf(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) +{ + if (sizeWanted <= 0) { + return; + } + HChannel context = (HChannel)handle->data; + int availSize = strlen(context->bufStd); + buf->base = (char *)context->bufStd + availSize; + buf->len = sizeof(context->bufStd) - availSize - 2; // reserve 2bytes +} + +void HdcClient::ReadStd(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) +{ + HChannel hChannel = (HChannel)stream->data; + HdcClient *thisClass = (HdcClient *)hChannel->clsChannel; + char *command = hChannel->bufStd; + if (nread <= 0) { + return; // error + } + thisClass->Send(hChannel->channelId, (uint8_t *)command, strlen(command)); + Base::ZeroArray(hChannel->bufStd); +} + +void HdcClient::ModifyTty(bool setOrRestore, uv_tty_t *tty) +{ + if (setOrRestore) { +#ifdef _WIN32 + uv_tty_set_mode(tty, UV_TTY_MODE_RAW); +#else + if (tcgetattr(STDIN_FILENO, &terminalState)) { + return; + } + termios tio; + if (tcgetattr(STDIN_FILENO, &tio)) { + return; + } + cfmakeraw(&tio); + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); +#endif + } else { +#ifndef _WIN32 + tcsetattr(STDIN_FILENO, TCSAFLUSH, &terminalState); +#endif + } +} + +void HdcClient::BindLocalStd(HChannel hChannel) +{ + if (command == CMDSTR_SHELL) { + bShellInteractive = true; + } + if (uv_guess_handle(STDIN_FILENO) != UV_TTY) { + WRITE_LOG(LOG_FATAL, "Not support std mode"); + return; + } + + WRITE_LOG(LOG_DEBUG, "Tty std mode"); + if (uv_tty_init(loopMain, &hChannel->stdoutTty, STDOUT_FILENO, 0) + || uv_tty_init(loopMain, &hChannel->stdinTty, STDIN_FILENO, 1)) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init failed"); + return; + } + hChannel->stdoutTty.data = hChannel; + ++hChannel->uvRef; + hChannel->stdinTty.data = hChannel; + ++hChannel->uvRef; + if (bShellInteractive) { + WRITE_LOG(LOG_DEBUG, "uv_tty_init uv_tty_set_mode"); + ModifyTty(true, &hChannel->stdinTty); + uv_read_start((uv_stream_t *)&hChannel->stdinTty, AllocStdbuf, ReadStd); + } +} + +void HdcClient::Connect(uv_connect_t *connection, int status) +{ + HdcClient *thisClass = (HdcClient *)connection->data; + delete connection; + HChannel hChannel = (HChannel)thisClass->channel; + if (status < 0 || uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) { + WRITE_LOG(LOG_FATAL, "connect failed"); + thisClass->FreeChannel(hChannel->channelId); + return; + } + thisClass->BindLocalStd(hChannel); + Base::SetTcpOptions((uv_tcp_t *)&hChannel->hWorkTCP); + uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, AllocCallback, ReadStream); +} + +int HdcClient::PreHandshake(HChannel hChannel, const uint8_t *buf) +{ + ChannelHandShake *hShake = (ChannelHandShake *)buf; + if (strncmp(hShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_BUF_CHECK; + } + // sync remote session id to local + uint32_t unOld = hChannel->channelId; + hChannel->channelId = ntohl(hShake->channelId); + AdminChannel(OP_UPDATE, unOld, hChannel); + WRITE_LOG(LOG_DEBUG, "Client channel handshake finished, use connectkey:%s", connectKey.c_str()); + // send config + // channel handshake step2 + if (memset_s(hShake->connectKey, sizeof(hShake->connectKey), 0, sizeof(hShake->connectKey)) != EOK + || memcpy_s(hShake->connectKey, sizeof(hShake->connectKey), connectKey.c_str(), connectKey.size()) != EOK) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_BUF_COPY; + } + Send(hChannel->channelId, reinterpret_cast(hShake), sizeof(ChannelHandShake)); + hChannel->handshakeOK = true; +#ifdef HDC_CHANNEL_KEEP_ALIVE + // Evaluation method, non long-term support + Send(hChannel->channelId, reinterpret_cast(CMDSTR_INNER_ENABLE_KEEPALIVE.c_str()), + CMDSTR_INNER_ENABLE_KEEPALIVE.size()); +#endif + return RET_SUCCESS; +} + +// read serverForClient(server)TCP data +int HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO) +{ + if (!hChannel->handshakeOK) { + return PreHandshake(hChannel, buf); + } +#ifdef UNIT_TEST + // Do not output to console when the unit test + return 0; +#endif + WRITE_LOG(LOG_DEBUG, "Client ReadChannel :%d", bytesIO); + string s(reinterpret_cast(buf), bytesIO); + (void)fprintf(stdout, "%s", s.c_str()); + fflush(stdout); + return 0; +} +} // namespace Hdc diff --git a/services/flashd/host/host_updater.cpp b/services/flashd/host/host_updater.cpp index 4de625d3023fa62e1052371a1ffff120561ceb12..9cd19ffb551528ebb0ae5d41c289632ab3d29c02 100755 --- a/services/flashd/host/host_updater.cpp +++ b/services/flashd/host/host_updater.cpp @@ -13,11 +13,19 @@ * limitations under the License. */ #include "host_updater.h" + +#include #include "common.h" +#include "flash_define.h" #include "transfer.h" #include "serial_struct.h" namespace Hdc { +static const std::string helpCmd = "flash"; +static const std::string updateCmd = "update "; +static const std::string flashCmd = "flash "; +static const std::string eraseCmd = "erase "; +static const std::string formatCmd = "format "; static const int PERCENT_FINISH = 100; static const uint32_t PERCENT_CLEAR = ((uint32_t)-1); HostUpdater::HostUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) @@ -41,24 +49,20 @@ bool HostUpdater::BeginTransfer(CtxFile &context, { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - if (argv == nullptr || argc < minParam || fileIndex >= argc) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - delete[]((char *)argv); - return false; - } + HOSTUPDATER_CHECK(!(argv == nullptr || argc < minParam || fileIndex >= argc), delete[]((char *)argv); + return false, "Invalid param for cmd \"%s\"", function.c_str()); + int maxParam = minParam; - if (strstr(payload, "-f") != nullptr) { + bool force = strstr(payload, "-f") != nullptr; + if (force) { maxParam += 1; } - if (argc != maxParam) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - delete[]((char *)argv); - return false; - } + HOSTUPDATER_CHECK(argc == maxParam, delete[]((char *)argv); + return false, "Invalid param for cmd \"%s\" %d", function.c_str(), maxParam); context.transferConfig.functionName = function; context.transferConfig.options = payload; - if (strcmp(argv[fileIndex], "-f") == 0) { + if (force && (fileIndex + 1 < argc) && strcmp(argv[fileIndex + 1], "-f") != 0) { context.localPath = argv[fileIndex + 1]; } else { context.localPath = argv[fileIndex]; @@ -66,27 +70,26 @@ bool HostUpdater::BeginTransfer(CtxFile &context, if (MatchPackageExtendName(context.localPath, ".img")) { context.transferConfig.compressType = COMPRESS_NONE; - } else if (function == CMDSTR_FLASH_PARTITION) { - context.transferConfig.compressType = COMPRESS_NONE; } else if (MatchPackageExtendName(context.localPath, ".bin")) { + const char *part = strstr(payload, "fastboot"); + HOSTUPDATER_CHECK(part != nullptr, delete[]((char *)argv); + return false, "Invalid image %s for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.transferConfig.compressType = COMPRESS_NONE; - } else if (!(MatchPackageExtendName(context.localPath, ".zip") || - MatchPackageExtendName(context.localPath, ".lz4") || - MatchPackageExtendName(context.localPath, ".gz2"))) { - LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); - delete[]((char *)argv); - return false; + } else { + HOSTUPDATER_CHECK((MatchPackageExtendName(context.localPath, ".zip") || + MatchPackageExtendName(context.localPath, ".lz4") || + MatchPackageExtendName(context.localPath, ".gz2")), delete[]((char *)argv); + return false, + "Invaid extend name \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); } WRITE_LOG(LOG_DEBUG, "BeginTransfer function: %s localPath: %s command: %s ", context.transferConfig.functionName.c_str(), context.localPath.c_str(), payload); // check path bool ret = Base::CheckDirectoryOrPath(context.localPath.c_str(), true, true); - if (!ret) { - LogMsg(MSG_FAIL, "Invaid file \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); - delete[]((char *)argv); - return false; - } + HOSTUPDATER_CHECK(ret, delete[]((char *)argv); + return false, + "Invaid path \"%s\" for cmd \"%s\"", context.localPath.c_str(), function.c_str()); context.taskQueue.push_back(context.localPath); RunQueue(context); return true; @@ -95,7 +98,7 @@ bool HostUpdater::BeginTransfer(CtxFile &context, std::string HostUpdater::GetFileName(const std::string &fileName) const { int32_t pos = fileName.find_last_of('/'); - if (pos < 0) { + if (pos < 0) { // win32 pos = fileName.find_last_of('\\'); } return fileName.substr(pos + 1, fileName.size()); @@ -132,15 +135,10 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int { int argc = 0; char **argv = Base::SplitCommandToArgs(payload, &argc); - if (argv == nullptr) { - LogMsg(MSG_FAIL, "Can not parser cmd \"%s\"", function.c_str()); - return false; - } + HOSTUPDATER_CHECK(argv != nullptr, return false, "Can not parser cmd \"%s\"", function.c_str()); delete[]((char *)argv); - if (argc < param) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - return false; - } + HOSTUPDATER_CHECK(argc >= param, return false, "Invalid param for cmd \"%s\" %d", function.c_str(), argc); + WRITE_LOG(LOG_DEBUG, "CheckCmd command: %s ", payload); int maxParam = param; if (strstr(payload, "-f") != nullptr) { @@ -150,10 +148,8 @@ bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int maxParam += 1; maxParam += 1; } - if (argc != maxParam) { - LogMsg(MSG_FAIL, "Invalid param for cmd \"%s\"", function.c_str()); - return false; - } + HOSTUPDATER_CHECK(argc == maxParam, return false, + "Invalid param for cmd \"%s\" %d %d", function.c_str(), argc, maxParam); return true; } @@ -161,14 +157,16 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons { const int cmdFroErase = 2; const int cmdFroFormat = 2; +#ifndef UPDATER_UT if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { return false; } +#endif bool ret = true; switch (command) { case CMD_UPDATER_BEGIN: { - std::string s(" Processing: 0%%"); - bSendProgress = true; + std::string s("Processing: 0%%"); + sendProgress = true; SendRawData(reinterpret_cast(s.data()), s.size()); break; } @@ -211,10 +209,10 @@ bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, cons void HostUpdater::ProcessProgress(uint32_t percentage) { - if (!bSendProgress) { + if (!sendProgress) { return; } - std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; + std::string backStr = "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"; std::string breakStr = "\n"; WRITE_LOG(LOG_INFO, "ProcessProgress %d", percentage); const int bufferSize = 128; @@ -222,39 +220,133 @@ void HostUpdater::ProcessProgress(uint32_t percentage) if (percentage == PERCENT_CLEAR) { // clear SendRawData(reinterpret_cast(backStr.data()), backStr.size()); SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); - bSendProgress = false; - return; - } - int len = sprintf_s(buffer.data(), buffer.size() - 1, "%s Processing: %3d%%", backStr.c_str(), percentage); - if (len <= 0) { + sendProgress = false; return; } + int len = sprintf_s(buffer.data(), buffer.size() - 1, "%sProcessing: %3d%%", backStr.c_str(), percentage); + HOSTUPDATER_CHECK(len > 0, return, "Failed to format progress info "); SendRawData(reinterpret_cast(buffer.data()), len); if (percentage == PERCENT_FINISH) { SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); - bSendProgress = false; + sendProgress = false; } } bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize) { - if (static_cast(payloadSize) < sizeof(uint16_t)) { - return false; - } + HOSTUPDATER_CHECK(static_cast(payloadSize) >= sizeof(uint16_t), + return false, "Failed to check payload size %d ", payloadSize); MessageLevel level = (MessageLevel)payload[1]; - if ((level == MSG_OK) && bSendProgress) { + if ((level == MSG_OK) && sendProgress) { ProcessProgress(PERCENT_FINISH); } std::string info((char*)(payload + sizeof(uint16_t)), payloadSize - sizeof(uint16_t)); if (!info.empty()) { LogMsg(level, "%s", info.c_str()); } - WRITE_LOG(LOG_DEBUG, "CheckUpdateContinue %d %s", level, info.c_str()); - ctxNow.taskQueue.pop_back(); + WRITE_LOG(LOG_DEBUG, "CheckUpdateContinue payloadSize %d %d %s", payloadSize, level, info.c_str()); + if (ctxNow.taskQueue.size() != 0) { + ctxNow.taskQueue.pop_back(); + } if (singalStop || !ctxNow.taskQueue.size()) { return false; } RunQueue(ctxNow); return true; } + +bool HostUpdater::CheckMatchUpdate(const std::string &input, + std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo) +{ + WRITE_LOG(LOG_DEBUG, "CheckMatchUpdate command:%s", input.c_str()); + size_t cmdLen = updateCmd.size(); + if (!strncmp(input.c_str(), updateCmd.c_str(), updateCmd.size())) { + cmdFlag = CMD_UPDATER_UPDATE_INIT; + cmdLen = updateCmd.size(); + } else if (!strncmp(input.c_str(), flashCmd.c_str(), flashCmd.size())) { + cmdFlag = CMD_UPDATER_FLASH_INIT; + cmdLen = flashCmd.size(); + } else if (!strncmp(input.c_str(), eraseCmd.c_str(), eraseCmd.size())) { + cmdFlag = CMD_UPDATER_ERASE; + cmdLen = eraseCmd.size(); + } else if (!strncmp(input.c_str(), formatCmd.c_str(), formatCmd.size())) { + cmdFlag = CMD_UPDATER_FORMAT; + cmdLen = formatCmd.size(); + } else { + return false; + } + if (input.size() <= cmdLen) { + stringError = "Incorrect command"; + bJumpDo = true; + } + return true; +} + +#ifdef UPDATER_UT +static std::string g_input = "yes"; +void HostUpdater::SetInput(const std::string &input) +{ + g_input = input; +} +#endif +bool HostUpdater::ConfirmCommand(const string &commandIn, bool &closeInput) +{ + std::string tip = ""; + if (!strncmp(commandIn.c_str(), updateCmd.c_str(), updateCmd.size())) { + closeInput = true; + } else if (!strncmp(commandIn.c_str(), flashCmd.c_str(), flashCmd.size())) { + tip = "Confirm flash partition"; + closeInput = true; + } else if (!strncmp(commandIn.c_str(), eraseCmd.c_str(), eraseCmd.size())) { + tip = "Confirm erase partition"; + } else if (!strncmp(commandIn.c_str(), formatCmd.c_str(), formatCmd.size())) { + tip = "Confirm format partition"; + } + if (tip.empty() || strstr(commandIn.c_str(), " -f") != nullptr) { // check if -f + return true; + } + const size_t minLen = strlen("yes"); + int retryCount = 0; + do { + printf("%s ? (Yes/No) ", tip.c_str()); + fflush(stdin); + std::string info = {}; + size_t i = 0; + while (1) { +#ifndef UPDATER_UT + char c = getchar(); +#else + char c = '\n'; + info = g_input; +#endif + if (c == '\r' || c == '\n') { + break; + } + if (c == ' ') { + continue; + } + if (i < minLen && isprint(c)) { + info.append(1, std::tolower(c)); + i++; + } + } + if (info == "n" || info == "no") { + return false; + } + if (info == "y" || info == "yes") { + return true; + } + retryCount++; + } while (retryCount < 3); // 3 retry max count + return (retryCount >= 3) ? false : true; // 3 retry max count +} + +void HostUpdater::SendRawData(uint8_t *bufPtr, const int size) +{ +#ifndef UPDATER_UT + HdcSessionBase *sessionBase = (HdcSessionBase *)clsSession; + sessionBase->ServerCommand(taskInfo->sessionId, + taskInfo->channelId, CMD_KERNEL_ECHO_RAW, bufPtr, size); +#endif +} } // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/host_updater.h b/services/flashd/host/host_updater.h index 08e5ec78c349cf51464795d9ae89fe1684a62458..f11a5d039f0c171af6bc6010e006f111688e194b 100755 --- a/services/flashd/host/host_updater.h +++ b/services/flashd/host/host_updater.h @@ -18,45 +18,51 @@ #include "transfer.h" namespace Hdc { +#define HOSTUPDATER_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + LogMsg(MSG_FAIL, __VA_ARGS__); \ + exper; \ + } + class HostUpdater : public HdcTransferBase { public: explicit HostUpdater(HTaskInfo hTaskInfo); virtual ~HostUpdater(); bool CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) override; + static bool CheckMatchUpdate(const std::string &input, std::string &stringError, uint16_t &cmdFlag, bool &bJumpDo); + static bool ConfirmCommand(const string &commandIn, bool &closeInput); +#ifdef UPDATER_UT + void OpenFile() + { + CheckMaster(&ctxNow); + } + static void SetInput(const std::string &input); +#endif private: void CheckMaster(CtxFile *context) override; - bool BeginTransfer(CtxFile &context, const std::string &function, const char *payload, int minParam, int fileIndex); bool CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize); void RunQueue(CtxFile &context); std::string GetFileName(const std::string &fileName) const; void ProcessProgress(uint32_t percentage); + void SendRawData(uint8_t *bufPtr, const int size); #ifdef UPDATER_UT void LogMsg(MessageLevel level, const char *msg, ...) { - va_list vaArgs; - va_start(vaArgs, msg); - string log = Base::StringFormat(msg, vaArgs); - va_end(vaArgs); - WRITE_LOG(LOG_DEBUG, "LogMsg %d %s", level, log.c_str()); return; } - void SendRawData(uint8_t *bufPtr, const int size) - { - WRITE_LOG(LOG_DEBUG, "SendRawData %d", size); - } bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) { - WRITE_LOG(LOG_DEBUG, "SendToAnother command %d size %d", command, size); + std::string s((char *)bufPtr, size); + WRITE_LOG(LOG_DEBUG, "SendToAnother command %d size %d %s", command, size, s.c_str()); return true; } #endif private: bool CheckCmd(const std::string &function, const char *payload, int param); - - bool bSendProgress = false; + bool sendProgress = false; }; } #endif \ No newline at end of file diff --git a/services/flashd/host/main.cpp b/services/flashd/host/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..3fe5d5b8656a363617d985282882151d20bd8ff9 --- /dev/null +++ b/services/flashd/host/main.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "flash_define.h" +#include "server.h" +#include "server_for_client.h" + +using namespace Hdc; + +static bool g_isServerMode = false; +static bool g_isPullServer = true; +static bool g_isPcDebugRun = false; +static bool g_isTCPorUSB = false; +static auto g_logLevel = LOG_LEVEL_FULL; +static int g_isTestMethod = 0; +static string g_connectKey = ""; +static string g_serverListenString = DEFAULT_SERVER_ADDR; + +namespace Hdc { +// return value: 0 == not command, 1 == one command, 2 == double command +int IsRegisterCommand(string &outCommand, const char *cmd, const char *cmdnext) +{ + string sCmdNext = cmdnext == nullptr ? string("") : string(cmdnext); + string doubleCommand = cmd + string(" ") + sCmdNext; + vector registerCommand; + registerCommand.push_back(CMDSTR_SOFTWARE_VERSION); + registerCommand.push_back(CMDSTR_SOFTWARE_HELP); + registerCommand.push_back(CMDSTR_TARGET_DISCOVER); + registerCommand.push_back(CMDSTR_LIST_TARGETS); + registerCommand.push_back(CMDSTR_CONNECT_ANY); + registerCommand.push_back(CMDSTR_CONNECT_TARGET); + registerCommand.push_back(CMDSTR_TARGET_REBOOT); + registerCommand.push_back(CMDSTR_SERVICE_KILL); + registerCommand.push_back(CMDSTR_SERVICE_START); + registerCommand.push_back(CMDSTR_TARGET_MODE); + + // flashd + registerCommand.push_back(CMDSTR_UPDATE_SYSTEM); + registerCommand.push_back(CMDSTR_FLASH_PARTITION); + registerCommand.push_back(CMDSTR_ERASE_PARTITION); + registerCommand.push_back(CMDSTR_FORMAT_PARTITION); + for (string v : registerCommand) { + if (doubleCommand == v) { + outCommand = doubleCommand; + return 2; // 2 error code + } + if (cmd == v) { + outCommand = cmd; + return 1; + } + } + return 0; +} + +void AppendCwdWhenTransfer(string &outCommand) +{ + if (outCommand != CMDSTR_FILE_SEND && outCommand != CMDSTR_FILE_RECV && outCommand != CMDSTR_APP_INSTALL + && outCommand != CMDSTR_APP_SIDELOAD) { + return; + } + char path[PATH_MAX] = ""; + size_t size = sizeof(path); + if (uv_cwd(path, &size) < 0) + return; + if (path[strlen(path) - 1] != Base::GetPathSep()) { + path[strlen(path)] = Base::GetPathSep(); + } + outCommand += outCommand.size() ? " -cwd " : "-cwd "; + outCommand += path; +} + +int SplitOptionAndCommand(int argc, const char **argv, string &outOption, string &outCommand) +{ + bool foundCommand = false; + int resultChild = 0; + // we want to start from 1, ignore argv[0], but it has issue + for (int i = 0; i < argc; ++i) { + if (!foundCommand) { + resultChild = IsRegisterCommand(outCommand, argv[i], (i == argc - 1) ? nullptr : argv[i + 1]); + if (resultChild > 0) { + foundCommand = true; + if (resultChild == 2) { // 2 error code + ++i; + } + AppendCwdWhenTransfer(outCommand); + continue; + } + } + if (foundCommand) { + outCommand += outCommand.size() ? " " : ""; + string rawCmd = argv[i]; + string packageCmd = Base::StringFormat("\"%s\"", argv[i]); + outCommand += rawCmd.find(" ") == string::npos ? rawCmd : packageCmd; + } else { + outOption += outOption.size() ? " " : ""; + outOption += argv[i]; + } + } + return 0; +} + +int RunServerMode(string &serverListenString) +{ + HdcServer server(true); + if (!server.Initial(serverListenString.c_str())) { + Base::PrintMessage("Initial failed"); + return -1; + } + server.WorkerPendding(); + return 0; +} + +int RunPcDebugMode(bool isPullServer, bool isTCPorUSB, int isTestMethod) +{ + pthread_t pt; + if (isPullServer) { + pthread_create(&pt, nullptr, TestBackgroundServerForClient, nullptr); + uv_sleep(200); // give time to start serverForClient,at least 200ms + } + TestRuntimeCommandSimple(isTCPorUSB, isTestMethod, true); + if (isPullServer) { + pthread_join(pt, nullptr); + WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Server finish"); + } + return 0; +} + +int RunClientMode(string &commands, string &serverListenString, string &connectKey, bool isPullServer) +{ + uv_loop_t loopMain; + uv_loop_init(&loopMain); + HdcClient client(false, serverListenString, &loopMain); + if (!commands.size()) { + Base::PrintMessage("Unknow operation command..."); + TranslateCommand::Usage(); + return 0; + } + if (!strncmp(commands.c_str(), CMDSTR_SERVICE_START.c_str(), CMDSTR_SERVICE_START.size()) + || !strncmp(commands.c_str(), CMDSTR_SERVICE_KILL.c_str(), CMDSTR_SERVICE_KILL.size()) + || !strncmp(commands.c_str(), CMDSTR_GENERATE_KEY.c_str(), CMDSTR_GENERATE_KEY.size())) { + client.CtrlServiceWork(commands.c_str()); + return 0; + } + if (isPullServer && serverListenString == DEFAULT_SERVER_ADDR + && Base::ProgramMutex(SERVER_NAME.c_str(), true) == 0) { + // default pullup, just default listenstr.If want to customer listen-string, please use 'hdc -m -s lanip:port' + HdcServer::PullupServer(DEFAULT_SERVER_ADDR.c_str()); + uv_sleep(300); // give time to start serverForClient,at least 300ms + } + client.Initial(connectKey); + client.ExecuteCommand(commands.c_str()); + return 0; +} + +bool ParseServerListenString(string &serverListenString, char *optarg) +{ + if (strlen(optarg) > 24) { // 24 min len + Base::PrintMessage("Unknow content of parament '-s'"); + return false; + } + char buf[BUF_SIZE_TINY] = ""; + if (strcpy_s(buf, sizeof(buf), optarg) < 0) { + return false; + } + char *p = strchr(buf, ':'); + if (!p) { // Only port + if (strlen(buf) > 5) { // 5 port len + Base::PrintMessage("The port-string's length must < 5"); + return false; + } + int port = atoi(buf); + if (port <= 0 || port > MAX_IP_PORT) { + Base::PrintMessage("Port range incorrect"); + return false; + } + snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "127.0.0.1:%d", port); + serverListenString = buf; + } else { + *p = '\0'; + int port = atoi(p + 1); + sockaddr_in addr; + if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(buf, port, &addr) < 0) { + Base::PrintMessage("-s content incorrect."); + return false; + } + serverListenString = optarg; + } + return true; +} + +bool GetCommandlineOptions(int optArgc, const char *optArgv[]) +{ + int ch = 0; + bool needExit = false; + opterr = 0; + // get option parameters first + while ((ch = getopt(optArgc, (char *const *)optArgv, "hvpfms:d:t:l:")) != -1) { + switch (ch) { + case 'h': { + string usage = Hdc::TranslateCommand::Usage(); + fprintf(stderr, "%s", usage.c_str()); + needExit = true; + return needExit; + } + case 'v': { + string ver = Base::GetVersion(); + fprintf(stdout, "%s\n", ver.c_str()); + needExit = true; + return needExit; + } + case 'f': { // [not-publish] + break; + } + case 'l': { + int logLevel = atoi(optarg); + if (logLevel < 0 || logLevel > LOG_LAST) { + Base::PrintMessage("Loglevel error!"); + needExit = true; + return needExit; + } + g_logLevel = logLevel; + Base::SetLogLevel(logLevel); + break; + } + case 'm': { // [not-publish] is server mode,or client mode + g_isServerMode = true; + break; + } + case 'p': { // [not-publish] not pullup server + g_isPullServer = false; + break; + } + case 't': { // key + if (strlen(optarg) > MAX_CONNECTKEY_SIZE) { + Base::PrintMessage("Sizeo of of parament '-t' %d is too long", strlen(optarg)); + needExit = true; + return needExit; + } + g_connectKey = optarg; + break; + } + case 's': { + if (!Hdc::ParseServerListenString(g_serverListenString, optarg)) { + needExit = true; + return needExit; + } + break; + } + case 'd': // [Undisclosed parameters] debug mode + g_isPcDebugRun = true; + if (optarg[0] == 't') { + g_isTCPorUSB = true; + } else if (optarg[0] == 'u') { + g_isTCPorUSB = false; + } else { + Base::PrintMessage("Unknown debug parameters"); + needExit = true; + return needExit; + } + g_isTestMethod = atoi(optarg + 1); + break; + case '?': + break; + default: { + Base::PrintMessage("Unknown parameters"); + needExit = true; + return needExit; + } + } + } + return needExit; +} +} + +#ifndef UNIT_TEST +// hdc -l4 -m -s ip:port|hdc -l4 -m +// hdc -l4 - s ip:port list targets +int main(int argc, const char *argv[]) +{ + string options; + string commands; + Hdc::SplitOptionAndCommand(argc, argv, options, commands); + int optArgc = 0; + char **optArgv = Base::SplitCommandToArgs(options.c_str(), &optArgc); + bool cmdOptionResult = GetCommandlineOptions(optArgc, (const char **)optArgv); + delete[]((char *)optArgv); + if (cmdOptionResult) { + return 0; + } + if (g_isServerMode) { + // -m server.Run alone in the background, no -s will be listen loopback address, + Base::SetLogLevel(g_logLevel); // default level LOG_LEVEL_FULL + Hdc::RunServerMode(g_serverListenString); + } else if (g_isPcDebugRun) { + Hdc::RunPcDebugMode(g_isPullServer, g_isTCPorUSB, g_isTestMethod); + } else { + Hdc::RunClientMode(commands, g_serverListenString, g_connectKey, g_isPullServer); + } + WRITE_LOG(LOG_DEBUG, "!!!!!!!!!Main finish main"); + return 0; +} +#endif // no UNIT_TEST diff --git a/services/flashd/host/server.cpp b/services/flashd/host/server.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1d8097bc0999379ddeeaabedae400997aa6f4e21 --- /dev/null +++ b/services/flashd/host/server.cpp @@ -0,0 +1,798 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server.h" + +#include "host_updater.h" +#include "flash_define.h" + +namespace Hdc { +HdcServer::HdcServer(bool serverOrDaemonIn) + : HdcSessionBase(serverOrDaemonIn) +{ + clsTCPClt = nullptr; + clsUSBClt = nullptr; + clsServerForClient = nullptr; + uv_rwlock_init(&daemonAdmin); + uv_rwlock_init(&forwardAdmin); +} + +HdcServer::~HdcServer() +{ + WRITE_LOG(LOG_DEBUG, "~HdcServer"); + uv_rwlock_destroy(&daemonAdmin); + uv_rwlock_destroy(&forwardAdmin); +} + +void HdcServer::ClearInstanceResource() +{ + TryStopInstance(); + Base::TryCloseLoop(&loopMain, "HdcServer::~HdcServer"); + if (clsTCPClt) { + delete clsTCPClt; + } + if (clsUSBClt) { + delete clsUSBClt; + } + if (clsServerForClient) { + delete (static_cast(clsServerForClient)); + } +} + +void HdcServer::TryStopInstance() +{ + ClearSessions(); + if (clsTCPClt) { + clsTCPClt->Stop(); + } + if (clsUSBClt) { + clsUSBClt->Stop(); + } + if (clsServerForClient) { + ((HdcServerForClient *)clsServerForClient)->Stop(); + } + ReMainLoopForInstanceClear(); + ClearMapDaemonInfo(); +} + +bool HdcServer::Initial(const char *listenString) +{ + if (Base::ProgramMutex(SERVER_NAME.c_str(), false) != 0) { + WRITE_LOG(LOG_FATAL, "Other instance already running, program mutex failed"); + return false; + } + clsServerForClient = new HdcServerForClient(true, listenString, this, &loopMain); + clsTCPClt = new HdcHostTCP(true, this); + clsUSBClt = new HdcHostUSB(true, this, ctxUSB); + if (!clsServerForClient || !clsTCPClt || !clsUSBClt) { + WRITE_LOG(LOG_FATAL, "Class init failed"); + return false; + } + (static_cast(clsServerForClient))->Initial(); + clsUSBClt->Initial(); + return true; +} + +bool HdcServer::PullupServerWin32(const char *path, const char *listenString) +{ +#ifdef _WIN32 + char buf[BUF_SIZE_SMALL] = ""; + char shortPath[MAX_PATH] = ""; + int ret = GetShortPathName(path, shortPath, MAX_PATH); + std::string runPath = shortPath; + if (ret == 0) { + int err = GetLastError(); + WRITE_LOG(LOG_WARN, "GetShortPath path:[%s] err:%d errmsg:%s", path, err, strerror(err)); + string uvPath = path; + runPath = uvPath.substr(uvPath.find_last_of("/\\") + 1); + } + WRITE_LOG(LOG_DEBUG, "server shortpath:[%s] runPath:[%s]", shortPath, runPath.c_str()); + if (sprintf_s(buf, sizeof(buf), "%s -l4 -s %s -m", runPath.c_str(), listenString) < 0) { + return false; + } + WRITE_LOG(LOG_DEBUG, "Run server in debug-forground, cmd:%s", buf); + STARTUPINFO si; + Base::ZeroStruct(si); + si.cb = sizeof(STARTUPINFO); + PROCESS_INFORMATION pi; + Base::ZeroStruct(pi); +#ifndef HDC_DEBUG + si.dwFlags = STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; +#endif + CreateProcess(nullptr, buf, nullptr, nullptr, true, CREATE_NEW_CONSOLE, nullptr, nullptr, &si, &pi); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); +#endif + return true; +} + +// Only detects that the default call is in the loop address, the other tubes are not +bool HdcServer::PullupServer(const char *listenString) +{ + char path[BUF_SIZE_SMALL] = ""; + size_t nPathSize = sizeof(path); + int ret = uv_exepath(path, &nPathSize); + if (ret < 0) { + WRITE_LOG(LOG_WARN, "uvexepath ret:%d error:%s", ret, uv_err_name(ret)); + return false; + } + +#ifdef _WIN32 + if (!PullupServerWin32(path, listenString)) { + return false; + } +#else + pid_t pc = fork(); // create process as daemon process + if (pc < 0) { + return false; + } else if (!pc) { + int i; + const int maxFD = 1024; + for (i = 0; i < maxFD; ++i) { + // close file pipe + close(i); + } + execl(path, "ohflash", "-m", "-s", listenString, nullptr); + exit(0); + return true; + } + // orig process +#endif + // wait little time, util backend-server work ready + uv_sleep(TIME_BASE); + return true; +} + +void HdcServer::ClearMapDaemonInfo() +{ + map::iterator iter; + uv_rwlock_rdlock(&daemonAdmin); + for (iter = mapDaemon.begin(); iter != mapDaemon.end();) { + string sKey = iter->first; + HDaemonInfo hDi = iter->second; + delete hDi; + ++iter; + } + uv_rwlock_rdunlock(&daemonAdmin); + uv_rwlock_wrlock(&daemonAdmin); + mapDaemon.clear(); + uv_rwlock_wrunlock(&daemonAdmin); +} + +void HdcServer::BuildDaemonVisableLine(HDaemonInfo hdi, bool fullDisplay, string &out) +{ + if (fullDisplay) { + string sConn; + string sStatus; + switch (hdi->connType) { + case CONN_TCP: + sConn = "TCP"; + break; + case CONN_USB: + sConn = "USB"; + break; + + case CONN_BT: + sConn = "BT"; + break; + default: + sConn = "UNKNOW"; + break; + } + switch (hdi->connStatus) { + case STATUS_READY: + sStatus = "Ready"; + break; + case STATUS_CONNECTED: + sStatus = "Connected"; + break; + case STATUS_OFFLINE: + sStatus = "Offline"; + break; + default: + sStatus = "UNKNOW"; + break; + } + out = Base::StringFormat("%s\t\t%s\t%s\t%s\n", hdi->connectKey.c_str(), sConn.c_str(), sStatus.c_str(), + hdi->devName.c_str()); + } else { + if (hdi->connStatus == STATUS_CONNECTED) { + out = Base::StringFormat("%s\n", hdi->connectKey.c_str()); + } + } +} + +string HdcServer::GetDaemonMapList(uint8_t opType) +{ + string ret; + bool fullDisplay = false; + if (OP_GET_STRLIST_FULL == opType) { + fullDisplay = true; + } + uv_rwlock_rdlock(&daemonAdmin); + map::iterator iter; + string echoLine; + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { + HDaemonInfo di = iter->second; + if (!di) { + continue; + } + echoLine = ""; + BuildDaemonVisableLine(di, fullDisplay, echoLine); + ret += echoLine; + } + uv_rwlock_rdunlock(&daemonAdmin); + return ret; +} + +void HdcServer::GetDaemonMapOnlyOne(HDaemonInfo &hDaemonInfoInOut) +{ + uv_rwlock_rdlock(&daemonAdmin); + string key; + for (auto &i : mapDaemon) { + if (i.second->connStatus == STATUS_CONNECTED) { + if (key == STRING_EMPTY) { + key = i.first; + } else { + key = STRING_EMPTY; + break; + } + } + } + if (key.size() > 0) { + hDaemonInfoInOut = mapDaemon[key]; + } + uv_rwlock_rdunlock(&daemonAdmin); +} + +string HdcServer::AdminDaemonMap(uint8_t opType, const string &connectKey, HDaemonInfo &hDaemonInfoInOut) +{ + string sRet; + switch (opType) { + case OP_ADD: { + HDaemonInfo pdiNew = new HdcDaemonInformation(); + *pdiNew = *hDaemonInfoInOut; + uv_rwlock_wrlock(&daemonAdmin); + if (!mapDaemon[hDaemonInfoInOut->connectKey]) { + mapDaemon[hDaemonInfoInOut->connectKey] = pdiNew; + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + case OP_GET_STRLIST: + case OP_GET_STRLIST_FULL: { + sRet = GetDaemonMapList(opType); + break; + } + case OP_QUERY: { + uv_rwlock_rdlock(&daemonAdmin); + if (mapDaemon.count(connectKey)) { + hDaemonInfoInOut = mapDaemon[connectKey]; + } + uv_rwlock_rdunlock(&daemonAdmin); + break; + } + case OP_REMOVE: { + uv_rwlock_wrlock(&daemonAdmin); + if (mapDaemon.count(connectKey)) { + mapDaemon.erase(connectKey); + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + case OP_GET_ANY: { + uv_rwlock_rdlock(&daemonAdmin); + map::iterator iter; + for (iter = mapDaemon.begin(); iter != mapDaemon.end(); ++iter) { + HDaemonInfo di = iter->second; + // usb will be auto connected + if (di->connStatus == STATUS_READY || di->connStatus == STATUS_CONNECTED) { + hDaemonInfoInOut = di; + break; + } + } + uv_rwlock_rdunlock(&daemonAdmin); + break; + } + case OP_GET_ONLY: { + GetDaemonMapOnlyOne(hDaemonInfoInOut); + break; + } + case OP_UPDATE: { // Cannot update the Object HDi lower key value by direct value + uv_rwlock_wrlock(&daemonAdmin); + HDaemonInfo hdi = mapDaemon[hDaemonInfoInOut->connectKey]; + if (hdi) { + *mapDaemon[hDaemonInfoInOut->connectKey] = *hDaemonInfoInOut; + } + uv_rwlock_wrunlock(&daemonAdmin); + break; + } + default: + break; + } + return sRet; +} + +void HdcServer::NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) +{ + HDaemonInfo hdiOld = nullptr; + AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld); + if (hdiOld == nullptr) { + return; + } + if (!freeOrClear) { // step1 + // update + HdcDaemonInformation diNew = *hdiOld; + diNew.connStatus = STATUS_OFFLINE; + HDaemonInfo hdiNew = &diNew; + AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew); + } else { // step2 + string usbMountPoint = hdiOld->usbMountPoint; + constexpr int waitDaemonReconnect = UV_DEFAULT_INTERVAL; // wait little time for daemon reinit + auto funcDelayUsbNotify = [this, usbMountPoint](const uint8_t flag, string &msg, const void *) -> void { + string s = usbMountPoint; + clsUSBClt->RemoveIgnoreDevice(s); + }; + if (usbMountPoint.size() > 0) { + // wait time for daemon reconnect + // If removed from maplist, the USB module will be reconnected, so it needs to wait for a while + Base::DelayDoSimple(&loopMain, waitDaemonReconnect, funcDelayUsbNotify); + } + } +} + +bool HdcServer::HandServerAuth(HSession hSession, SessionHandShake &handshake) +{ + bool ret = false; + int retChild = 0; + string bufString; + switch (handshake.authType) { + case AUTH_TOKEN: { + void *ptr = nullptr; + bool retChild = HdcAuth::KeylistIncrement(hSession->listKey, hSession->authKeyIndex, &ptr); + // HdcAuth::FreeKey will be effect at funciton 'FreeSession' + if (!retChild) { + // Iteration call certificate authentication + handshake.authType = AUTH_PUBLICKEY; + ret = HandServerAuth(hSession, handshake); + break; + } + char sign[BUF_SIZE_DEFAULT2] = { 0 }; + retChild = HdcAuth::AuthSign(ptr, (const unsigned char *)handshake.buf.c_str(), handshake.buf.size(), sign); + if (!retChild) { + break; + } + handshake.buf = string(sign, retChild); + handshake.authType = AUTH_SIGNATURE; + bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + case AUTH_PUBLICKEY: { + char bufPrivateKey[BUF_SIZE_DEFAULT2] = ""; + retChild = HdcAuth::GetPublicKeyFileBuf((unsigned char *)bufPrivateKey, sizeof(bufPrivateKey)); + if (!retChild) { + break; + } + handshake.buf = string(bufPrivateKey, retChild); + handshake.authType = AUTH_PUBLICKEY; + bufString = SerialStruct::SerializeToString(handshake); + Send(hSession->sessionId, 0, CMD_KERNEL_HANDSHAKE, (uint8_t *)bufString.c_str(), bufString.size()); + ret = true; + break; + } + default: + break; + } + return ret; +} + +bool HdcServer::ServerSessionHandshake(HSession hSession, uint8_t *payload, int payloadSize) +{ + // session handshake step3 + string s = string((char *)payload, payloadSize); + Hdc::HdcSessionBase::SessionHandShake handshake; + SerialStruct::ParseFromString(handshake, s); + if (handshake.banner != HANDSHAKE_MESSAGE.c_str()) { + WRITE_LOG(LOG_DEBUG, "Hello failed"); + return false; + } + if (handshake.authType != AUTH_OK) { + if (!HandServerAuth(hSession, handshake)) { + WRITE_LOG(LOG_DEBUG, "Auth failed"); + return false; + } + return true; + } + // handshake auth OK + HDaemonInfo hdiOld = nullptr; + AdminDaemonMap(OP_QUERY, hSession->connectKey, hdiOld); + if (!hdiOld) { + return false; + } + HdcDaemonInformation diNew = *hdiOld; + HDaemonInfo hdiNew = &diNew; + // update + hdiNew->connStatus = STATUS_CONNECTED; + if (handshake.buf.size() > sizeof(hdiNew->devName) || !handshake.buf.size()) { + hdiNew->devName = "unknow..."; + } else { + hdiNew->devName = handshake.buf; + } + AdminDaemonMap(OP_UPDATE, hSession->connectKey, hdiNew); + hSession->handshakeOK = true; + return true; +} + +bool HdcServer::FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, + const int payloadSize) +{ + bool ret = true; + HdcServerForClient *pSfc = static_cast(clsServerForClient); + // When you first initialize, ChannelID may be 0 + HChannel hChannel = pSfc->AdminChannel(OP_QUERY, channelId, nullptr); + if (CMD_KERNEL_HANDSHAKE == command) { + ret = ServerSessionHandshake(hSession, payload, payloadSize); + WRITE_LOG(LOG_DEBUG, "Session handshake %s", ret ? "successful" : "failed"); + return ret; + } + if (!hChannel) { + if (command == CMD_KERNEL_CHANNEL_CLOSE) { + // Daemon close channel and want to notify server close channel also, but it may has been + // closed by herself + } else { + // Client may be ctrl+c and Server remove channel. notify server async + } + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + return true; + } + switch (command) { + case CMD_KERNEL_ECHO_RAW: { // Native shell data output + pSfc->EchoClientRaw(channelId, payload, payloadSize); + break; + } + case CMD_KERNEL_ECHO: { + MessageLevel level = (MessageLevel)*payload; + string s(reinterpret_cast(payload + 1), payloadSize - 1); + pSfc->EchoClient(hChannel, level, s.c_str()); + WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_ECHO size:%d", payloadSize - 1); + break; + } + case CMD_KERNEL_CHANNEL_CLOSE: { + WRITE_LOG(LOG_DEBUG, "CMD_KERNEL_CHANNEL_CLOSE channelid:%d", channelId); + ClearOwnTasks(hSession, channelId); + // Forcibly closing the tcp handle here may result in incomplete data reception on the client side + HdcServerForClient *sfc = static_cast(hChannel->clsChannel); + sfc->FreeChannel(hChannel->channelId); + if (*payload == 1) { + --(*payload); + Send(hSession->sessionId, channelId, CMD_KERNEL_CHANNEL_CLOSE, payload, 1); + } + break; + } + case CMD_FORWARD_SUCCESS: { + // add to local + HdcForwardInformation di; + HForwardInfo pdiNew = &di; + pdiNew->channelId = channelId; + pdiNew->sessionId = hSession->sessionId; + pdiNew->forwardDirection = ((char *)payload)[0] == '1'; + pdiNew->taskString = (char *)payload + 2; // 2 len + AdminForwardMap(OP_ADD, STRING_EMPTY, pdiNew); + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); // detch client channel + break; + } + default: { + HSession hSession = AdminSession(OP_QUERY, hChannel->targetSessionId, nullptr); + if (!hSession) { + return false; + } + ret = DispatchTaskData(hSession, hChannel->channelId, command, payload, payloadSize); + break; + } + } + return ret; +} + +void HdcServer::BuildForwardVisableLine(bool fullOrSimble, HForwardInfo hfi, string &echo) +{ + string buf; + if (fullOrSimble) { + buf = Base::StringFormat("'%s'\t%s\n", hfi->taskString.c_str(), + hfi->forwardDirection ? "[Forward]" : "[Reverse]"); + } else { + buf = Base::StringFormat("%s\n", hfi->taskString.c_str()); + } + echo += buf; +} + +string HdcServer::AdminForwardMap(uint8_t opType, const string &taskString, HForwardInfo &hForwardInfoInOut) +{ + string sRet; + switch (opType) { + case OP_ADD: { + HForwardInfo pfiNew = new HdcForwardInformation(); + *pfiNew = *hForwardInfoInOut; + uv_rwlock_wrlock(&forwardAdmin); + if (!mapForward[hForwardInfoInOut->taskString]) { + mapForward[hForwardInfoInOut->taskString] = pfiNew; + } + uv_rwlock_wrunlock(&forwardAdmin); + break; + } + case OP_GET_STRLIST: + case OP_GET_STRLIST_FULL: { + uv_rwlock_rdlock(&forwardAdmin); + map::iterator iter; + for (iter = mapForward.begin(); iter != mapForward.end(); ++iter) { + HForwardInfo di = iter->second; + if (!di) { + continue; + } + BuildForwardVisableLine(opType == OP_GET_STRLIST_FULL, di, sRet); + } + uv_rwlock_rdunlock(&forwardAdmin); + break; + } + case OP_QUERY: { + uv_rwlock_rdlock(&forwardAdmin); + if (mapForward.count(taskString)) { + hForwardInfoInOut = mapForward[taskString]; + } + uv_rwlock_rdunlock(&forwardAdmin); + break; + } + case OP_REMOVE: { + uv_rwlock_wrlock(&forwardAdmin); + if (mapForward.count(taskString)) { + mapForward.erase(taskString); + } + uv_rwlock_wrunlock(&forwardAdmin); + break; + } + default: + break; + } + return sRet; +} + +void HdcServer::UsbPreConnect(uv_timer_t *handle) +{ + HSession hSession = (HSession)handle->data; + bool stopLoop = false; + HdcServer *hdcServer = (HdcServer *)hSession->classInstance; + const int usbConnectRetryMax = 5; + while (true) { + WRITE_LOG(LOG_DEBUG, "HdcServer::UsbPreConnect"); + if (++hSession->hUSB->retryCount > usbConnectRetryMax) { // max 15s + hdcServer->FreeSession(hSession->sessionId); + stopLoop = true; + break; + } + HDaemonInfo pDi = nullptr; + if (hSession->connectKey == "any") { + hdcServer->AdminDaemonMap(OP_GET_ANY, hSession->connectKey, pDi); + } else { + hdcServer->AdminDaemonMap(OP_QUERY, hSession->connectKey, pDi); + } + if (!pDi || !pDi->usbMountPoint.size()) { + break; + } + HdcHostUSB *hdcHostUSB = (HdcHostUSB *)hSession->classModule; + hdcHostUSB->ConnectDetectDaemon(hSession, pDi); + stopLoop = true; + break; + } + if (stopLoop && !uv_is_closing((const uv_handle_t *)handle)) { + uv_close((uv_handle_t *)handle, Base::CloseTimerCallback); + } +} + +// -1,has old,-2 error +int HdcServer::CreateConnect(const string &connectKey) +{ + uint8_t connType = 0; + if (connectKey.find(":") != std::string::npos) { // TCP + connType = CONN_TCP; + } else { // USB + connType = CONN_USB; + } + HDaemonInfo hdi = nullptr; + if (connectKey == "any") { + return RET_SUCCESS; + } + AdminDaemonMap(OP_QUERY, connectKey, hdi); + if (hdi == nullptr) { + HdcDaemonInformation di; + Base::ZeroStruct(di); + di.connectKey = connectKey; + di.connType = connType; + di.connStatus = STATUS_UNKNOW; + HDaemonInfo pDi = (HDaemonInfo)&di; + AdminDaemonMap(OP_ADD, "", pDi); + AdminDaemonMap(OP_QUERY, connectKey, hdi); + } + if (!hdi || hdi->connStatus == STATUS_CONNECTED) { + return ERR_GENERIC; + } + HSession hSession = nullptr; + if (CONN_TCP == connType) { + hSession = clsTCPClt->ConnectDaemon(connectKey); + } else { + hSession = MallocSession(true, CONN_USB, clsUSBClt); + hSession->connectKey = connectKey; + uv_timer_t *waitTimeDoCmd = new uv_timer_t; + uv_timer_init(&loopMain, waitTimeDoCmd); + waitTimeDoCmd->data = hSession; + uv_timer_start(waitTimeDoCmd, UsbPreConnect, 10, 100); // 10 100 repeat + } + if (!hSession) { + return ERR_BUF_ALLOC; + } + HDaemonInfo hdiQuery = nullptr; + AdminDaemonMap(OP_QUERY, connectKey, hdiQuery); + if (hdiQuery) { + HdcDaemonInformation diNew = *hdiQuery; + diNew.hSession = hSession; + HDaemonInfo hdiNew = &diNew; + AdminDaemonMap(OP_UPDATE, hdiQuery->connectKey, hdiNew); + } + return RET_SUCCESS; +} + +void HdcServer::AttachChannel(HSession hSession, const uint32_t channelId) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + int ret = 0; + if (!hChannel) { + return; + } + uv_tcp_init(&hSession->childLoop, &hChannel->hChildWorkTCP); + hChannel->hChildWorkTCP.data = hChannel; + hChannel->targetSessionId = hSession->sessionId; + if ((ret = uv_tcp_open((uv_tcp_t *)&hChannel->hChildWorkTCP, hChannel->fdChildWorkTCP)) < 0) { + WRITE_LOG(LOG_DEBUG, "Hdcserver AttachChannel uv_tcp_open failed %s, channelid:%d fdChildWorkTCP:%d", + uv_err_name(ret), hChannel->channelId, hChannel->fdChildWorkTCP); + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP); + return; + } + Base::SetTcpOptions((uv_tcp_t *)&hChannel->hChildWorkTCP); + uv_read_start((uv_stream_t *)&hChannel->hChildWorkTCP, hSfc->AllocCallback, hSfc->ReadStream); +}; + +void HdcServer::DeatchChannel(HSession hSession, const uint32_t channelId) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + if (!hChannel) { + return; + } + if (hChannel->childCleared) { + WRITE_LOG(LOG_DEBUG, "Childchannel has already freed, cid:%d", channelId); + return; + } + uint8_t count = 1; + Send(hSession->sessionId, hChannel->channelId, CMD_KERNEL_CHANNEL_CLOSE, &count, 1); + if (uv_is_closing((const uv_handle_t *)&hChannel->hChildWorkTCP)) { + Base::DoNextLoop(&hSession->childLoop, hChannel, [](const uint8_t flag, string &msg, const void *data) { + HChannel hChannel = (HChannel)data; + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free direct, cid:%d", hChannel->channelId); + }); + } else { + Base::TryCloseHandle((uv_handle_t *)&hChannel->hChildWorkTCP, [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + hChannel->childCleared = true; + WRITE_LOG(LOG_DEBUG, "Childchannel free callback, cid:%d", hChannel->channelId); + }); + } +}; + +bool HdcServer::ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, + uint8_t *bufPtr, const int size) +{ + HdcServerForClient *hSfc = static_cast(clsServerForClient); + HChannel hChannel = hSfc->AdminChannel(OP_QUERY, channelId, nullptr); + HSession hSession = AdminSession(OP_QUERY, sessionId, nullptr); + if (!hChannel || !hSession) { + return false; + } + return FetchCommand(hSession, channelId, command, bufPtr, size); +} + +// clang-format off +bool HdcServer::RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, + const uint16_t command, uint8_t *payload, const int payloadSize) +// clang-format on +{ + bool ret = true; + hTaskInfo->ownerSessionClass = this; + switch (command) { + case CMD_UNITY_BUGREPORT_INIT: + case CMD_UNITY_BUGREPORT_DATA: + ret = TaskCommandDispatch(hTaskInfo, TYPE_UNITY, command, payload, payloadSize); + break; + case CMD_FILE_INIT: + case CMD_FILE_BEGIN: + case CMD_FILE_CHECK: + case CMD_FILE_DATA: + case CMD_FILE_FINISH: + ret = TaskCommandDispatch(hTaskInfo, TASK_FILE, command, payload, payloadSize); + break; + case CMD_FORWARD_INIT: + case CMD_FORWARD_CHECK: + case CMD_FORWARD_CHECK_RESULT: + case CMD_FORWARD_ACTIVE_MASTER: + case CMD_FORWARD_DATA: + case CMD_FORWARD_FREE_CONTEXT: + ret = TaskCommandDispatch(hTaskInfo, TASK_FORWARD, command, payload, payloadSize); + break; + case CMD_APP_INIT: + case CMD_APP_SIDELOAD: + case CMD_APP_BEGIN: + case CMD_APP_FINISH: + case CMD_APP_UNINSTALL: + ret = TaskCommandDispatch(hTaskInfo, TASK_APP, command, payload, payloadSize); + break; + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_CHECK: + case CMD_UPDATER_BEGIN: + case CMD_UPDATER_DATA: + case CMD_UPDATER_FINISH: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: + case CMD_UPDATER_PROGRESS: + ret = TaskCommandDispatch(hTaskInfo, TASK_UPDATER, command, payload, payloadSize); + break; + default: + WRITE_LOG(LOG_WARN, "RedirectToTask error command:%d ", command); + ret = false; + break; + } + return ret; +} + +bool HdcServer::RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) +{ + bool ret = true; + switch (hTask->taskType) { + case TYPE_SHELL: + WRITE_LOG(LOG_DEBUG, "Server not enable unity/shell"); + break; + case TYPE_UNITY: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FILE: + ret = DoTaskRemove(hTask, op); + break; + case TASK_FORWARD: + ret = DoTaskRemove(hTask, op); + break; + case TASK_APP: + ret = DoTaskRemove(hTask, op); + break; + case TASK_UPDATER: + ret = DoTaskRemove(hTask, op); + break; + default: + ret = false; + break; + } + return ret; +} +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/host/server_for_client.cpp b/services/flashd/host/server_for_client.cpp new file mode 100755 index 0000000000000000000000000000000000000000..496b0bbf7c35ac77132c2b653f144e761bc61cf8 --- /dev/null +++ b/services/flashd/host/server_for_client.cpp @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "server_for_client.h" + +#include "flash_define.h" +#include "server.h" + +namespace Hdc { +HdcServerForClient::HdcServerForClient(const bool serverOrClient, const string &addrString, void *pClsServer, + uv_loop_t *loopMainIn) + : HdcChannelBase(serverOrClient, addrString, loopMainIn) +{ + clsServer = pClsServer; +} + +HdcServerForClient::~HdcServerForClient() +{ + WRITE_LOG(LOG_DEBUG, "~HdcServerForClient"); +} + +void HdcServerForClient::Stop() +{ + Base::TryCloseHandle((uv_handle_t *)&tcpListen); +} + +uint16_t HdcServerForClient::GetTCPListenPort() +{ + return channelPort; +} + +void HdcServerForClient::AcceptClient(uv_stream_t *server, int status) +{ + uv_tcp_t *pServTCP = (uv_tcp_t *)server; + HdcServerForClient *thisClass = (HdcServerForClient *)pServTCP->data; + HChannel hChannel = nullptr; + uint32_t uid = thisClass->MallocChannel(&hChannel); + if (!hChannel) { + return; + } + if (uv_accept(server, (uv_stream_t *)&hChannel->hWorkTCP) < 0) { + thisClass->FreeChannel(uid); + return; + } + WRITE_LOG(LOG_DEBUG, "HdcServerForClient acceptClient"); + // limit first recv + int bufMaxSize = 0; + uv_recv_buffer_size((uv_handle_t *)&hChannel->hWorkTCP, &bufMaxSize); + auto funcChannelHeaderAlloc = [](uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf) -> void { + HChannel context = (HChannel)handle->data; + Base::ReallocBuf(&context->ioBuf, &context->bufSize, context->availTailIndex, sizeWanted); + buf->base = (char *)context->ioBuf + context->availTailIndex; + buf->len = sizeof(struct ChannelHandShake) + DWORD_SERIALIZE_SIZE; // only recv static size + }; + // first packet static size, after this packet will be dup for normal recv + uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, funcChannelHeaderAlloc, ReadStream); + // channel handshake step1 + struct ChannelHandShake handShake; + Base::ZeroStruct(handShake); + if (EOK == strcpy_s(handShake.banner, sizeof(handShake.banner), HANDSHAKE_MESSAGE.c_str())) { + handShake.channelId = htonl(hChannel->channelId); + thisClass->Send(hChannel->channelId, (uint8_t *)&handShake, sizeof(struct ChannelHandShake)); + } +} + +void HdcServerForClient::SetTCPListen() +{ + tcpListen.data = this; + struct sockaddr_in addr; + uv_tcp_init(loopMain, &tcpListen); + uv_ip4_addr(channelHost.c_str(), channelPort, &addr); + uv_tcp_bind(&tcpListen, (const struct sockaddr *)&addr, 0); + uv_listen((uv_stream_t *)&tcpListen, 128, (uv_connection_cb)AcceptClient); // 128 client +} + +int HdcServerForClient::Initial() +{ + if (!clsServer) { + WRITE_LOG(LOG_FATAL, "Module client initial failed"); + return -1; + } + if (!channelHostPort.size() || !channelHost.size() || !channelPort) { + WRITE_LOG(LOG_FATAL, "Listen string initial failed"); + return -2; // 2 error code + } + SetTCPListen(); + return 0; +} + +void HdcServerForClient::EchoClient(HChannel hChannel, MessageLevel level, const char *msg, ...) +{ + string logInfo = ""; + switch (level) { + case MSG_FAIL: + logInfo = MESSAGE_FAIL; + break; + case MSG_INFO: + logInfo = MESSAGE_INFO; + break; + default: // successful, not append extra info + break; + } + va_list vaArgs; + va_start(vaArgs, msg); + string log = logInfo + Base::StringFormat(msg, vaArgs); + va_end(vaArgs); + if (log.back() != '\n') { + log += "\r\n"; + } + Send(hChannel->channelId, (uint8_t *)log.c_str(), log.size()); +} + +void HdcServerForClient::EchoClientRaw(const uint32_t channelId, uint8_t *payload, const int payloadSize) +{ + Send(channelId, payload, payloadSize); +} + +bool HdcServerForClient::SendToDaemon(HChannel hChannel, const uint16_t commandFlag, uint8_t *bufPtr, const int bufSize) +{ + HDaemonInfo hdi = nullptr; + bool ret = false; + HdcServer *ptrServer = (HdcServer *)clsServer; + while (true) { + ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); + if (hdi == nullptr) { + break; + } + if (hdi->connStatus != STATUS_CONNECTED) { + break; + } + if (!hdi->hSession) { + break; + } + if (ptrServer->Send(hdi->hSession->sessionId, hChannel->channelId, commandFlag, bufPtr, bufSize) < 0) { + break; + } + ret = true; + break; + } + return ret; +} + +void HdcServerForClient::OrderFindTargets(HChannel hChannel) +{ + int count = 0; + EchoClient(hChannel, MSG_INFO, "Please add HDC server's firewall ruler to allow udp incoming, udpport:%d", + DEFAULT_PORT); + HdcServer *ptrServer = (HdcServer *)clsServer; + ptrServer->clsTCPClt->FindLanDaemon(); + list &lst = ptrServer->clsTCPClt->lstDaemonResult; + // refresh main list + HdcDaemonInformation di; + while (!lst.empty()) { + Base::ZeroStruct(di); + ++count; + di.connectKey = lst.front(); + di.connType = CONN_TCP; + di.connStatus = STATUS_READY; + HDaemonInfo pDi = (HDaemonInfo)&di; + ptrServer->AdminDaemonMap(OP_ADD, STRING_EMPTY, pDi); + lst.pop_front(); + } + EchoClient(hChannel, MSG_INFO, "Broadcast find daemon, total:%d", count); +#ifdef UNIT_TEST + string bufString = std::to_string(count); + Base::WriteBinFile((UT_TMP_PATH + "/base-discover.result").c_str(), (uint8_t *)bufString.c_str(), bufString.size(), + true); +#endif +} + +void HdcServerForClient::OrderConnecTargetResult(uv_timer_t *req) +{ + HChannel hChannel = (HChannel)req->data; + HdcServerForClient *thisClass = (HdcServerForClient *)hChannel->clsChannel; + HdcServer *ptrServer = (HdcServer *)thisClass->clsServer; + bool bConnectOK = false; + bool bExitRepet = false; + HDaemonInfo hdi = nullptr; + string sRet; + string target = std::string(hChannel->bufStd + 2); + if (target == "any") { + ptrServer->AdminDaemonMap(OP_GET_ANY, target, hdi); + } else { + ptrServer->AdminDaemonMap(OP_QUERY, target, hdi); + } + if (hdi && STATUS_CONNECTED == hdi->connStatus) { + bConnectOK = true; + } + while (true) { + if (bConnectOK) { + bExitRepet = true; + sRet = "Connect OK"; + thisClass->EchoClient(hChannel, MSG_OK, (char *)sRet.c_str()); + break; + } else { + uint16_t *bRetryCount = (uint16_t *)hChannel->bufStd; + ++(*bRetryCount); + if (*bRetryCount > 500) { // 500 ms + bExitRepet = true; + sRet = "Connect failed"; + thisClass->EchoClient(hChannel, MSG_FAIL, (char *)sRet.c_str()); + break; + } + } + break; + } + if (bExitRepet) { + thisClass->FreeChannel(hChannel->channelId); + Base::TryCloseHandle((const uv_handle_t *)req, Base::CloseTimerCallback); + } +} + +bool HdcServerForClient::NewConnectTry(void *ptrServer, HChannel hChannel, const string &connectKey) +{ + int childRet = ((HdcServer *)ptrServer)->CreateConnect(connectKey); + bool ret = false; + if (-1 == childRet) { + EchoClient(hChannel, MSG_INFO, "Target is connected, repeat operation"); + } else if (-2 == childRet) { // 2 error code + EchoClient(hChannel, MSG_FAIL, "CreateConnect failed"); + WRITE_LOG(LOG_FATAL, "CreateConnect failed"); + } else { + Base::ZeroBuf(hChannel->bufStd, 2); // 2 len + childRet = snprintf_s(hChannel->bufStd + 2, sizeof(hChannel->bufStd) - 2, // 2 len + sizeof(hChannel->bufStd) - 3, "%s", (char *)connectKey.c_str()); // 3 len + if (childRet > 0) { + Base::TimerUvTask(loopMain, hChannel, OrderConnecTargetResult, 10); // 10 repeat + ret = true; + } + } + return ret; +} + +bool HdcServerForClient::CommandRemoveSession(HChannel hChannel, const char *connectKey) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HDaemonInfo hdiOld = nullptr; + ((HdcServer *)ptrServer)->AdminDaemonMap(OP_QUERY, connectKey, hdiOld); + if (!hdiOld) { + EchoClient(hChannel, MSG_FAIL, "No target available"); + return false; + } + ((HdcServer *)ptrServer)->FreeSession(hdiOld->hSession->sessionId); + return true; +} + +bool HdcServerForClient::CommandRemoveForward(const string &forwardKey) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HForwardInfo hfi = nullptr; + ptrServer->AdminForwardMap(OP_QUERY, forwardKey, hfi); + if (!hfi) { + return false; + } + HSession hSession = ptrServer->AdminSession(OP_QUERY, hfi->sessionId, nullptr); + if (!hSession) { + return false; + } + ptrServer->ClearOwnTasks(hSession, hfi->channelId); + FreeChannel(hfi->channelId); + hfi = nullptr; + ptrServer->AdminForwardMap(OP_REMOVE, forwardKey, hfi); + return true; +} + +void HdcServerForClient::GetTargetList(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + uint16_t cmd = OP_GET_STRLIST; + if (formatCommand->parameters == "v") { + cmd = OP_GET_STRLIST_FULL; + } + HDaemonInfo hdi = nullptr; + string sRet = ptrServer->AdminDaemonMap(cmd, STRING_EMPTY, hdi); + if (!sRet.length()) { + sRet = EMPTY_ECHO; + } + EchoClient(hChannel, MSG_OK, (char *)sRet.c_str()); +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/base-list.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); +#endif +} + +bool HdcServerForClient::GetAnyTarget(HChannel hChannel) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HDaemonInfo hdi = nullptr; + ptrServer->AdminDaemonMap(OP_GET_ANY, STRING_EMPTY, hdi); + if (!hdi) { + EchoClient(hChannel, MSG_FAIL, "No target available"); + return false; + } + // can not use hdi->connectKey.This memory may be released to re-Malloc + string connectKey = hdi->connectKey; + bool ret = NewConnectTry(ptrServer, hChannel, connectKey); +#ifdef UNIT_TEST + Base::WriteBinFile((UT_TMP_PATH + "/base-any.result").c_str(), (uint8_t *)MESSAGE_SUCCESS.c_str(), + MESSAGE_SUCCESS.size(), true); +#endif + return ret; +} + +bool HdcServerForClient::RemoveForward(HChannel hChannel, const char *parameterString) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + if (parameterString == nullptr) { // remove all + HForwardInfo hfi = nullptr; // dummy + string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST, "", hfi); + if (!echo.length()) { + return false; + } + vector filterStrings; + Base::SplitString(echo, string("\n"), filterStrings); + for (auto &&s : filterStrings) { + if (!CommandRemoveForward(s.c_str())) { + EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed,ruler:%s", s.c_str()); + } + } + } else { // remove single + if (!CommandRemoveForward(parameterString)) { + EchoClient(hChannel, MSG_FAIL, "Remove forward ruler failed,ruler:%s", parameterString); + } + } + return true; +} + +bool HdcServerForClient::DoCommandLocal(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + const char *parameterString = formatCommand->parameters.c_str(); + bool ret = false; + // Main thread command, direct Listen main thread + switch (formatCommand->cmdFlag) { + case CMD_KERNEL_TARGET_DISCOVER: { + OrderFindTargets(hChannel); + ret = false; + break; + } + case CMD_KERNEL_TARGET_LIST: { + GetTargetList(hChannel, formatCommandInput); + ret = false; + break; + } + case CMD_KERNEL_TARGET_ANY: { + ret = GetAnyTarget(hChannel); + break; + } + case CMD_KERNEL_TARGET_CONNECT: { + ret = NewConnectTry(ptrServer, hChannel, parameterString); + break; + } + case CMD_KERNEL_TARGET_DISCONNECT: { + CommandRemoveSession(hChannel, parameterString); + break; + } + case CMD_KERNEL_SERVER_KILL: { + WRITE_LOG(LOG_DEBUG, "Recv server kill command"); + uv_stop(loopMain); + ret = true; + break; + } + // task will be global task,Therefore, it can only be controlled in the global session. + case CMD_FORWARD_LIST: { + HForwardInfo hfi = nullptr; // dummy + string echo = ptrServer->AdminForwardMap(OP_GET_STRLIST_FULL, "", hfi); + if (!echo.length()) { + echo = EMPTY_ECHO; + } + EchoClient(hChannel, MSG_OK, (char *)echo.c_str()); + break; + } + case CMD_FORWARD_REMOVE: { + RemoveForward(hChannel, parameterString); + break; + } + case CMD_KERNEL_ENABLE_KEEPALIVE: { + // just use for 'list targets' now + hChannel->keepAlive = true; + ret = true; + break; + } + default: { + EchoClient(hChannel, MSG_FAIL, "ExecuteCommand need connect-key?"); + break; + } + } + return ret; +} + +bool HdcServerForClient::TaskCommand(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + HdcServer *ptrServer = (HdcServer *)clsServer; + int sizeSend = formatCommand->parameters.size(); + string cmdFlag; + uint8_t sizeCmdFlag = 0; + if (CMD_FILE_INIT == formatCommand->cmdFlag) { + cmdFlag = "send "; + sizeCmdFlag = 5; // 5: cmdFlag send size + } else if (CMD_FORWARD_INIT == formatCommand->cmdFlag) { + cmdFlag = "fport "; + sizeCmdFlag = 6; // 6: cmdFlag fport size + } else if (CMD_APP_INIT == formatCommand->cmdFlag) { + cmdFlag = "install "; + sizeCmdFlag = 8; // 8: cmdFlag install size + } else if (CMD_APP_UNINSTALL == formatCommand->cmdFlag) { + cmdFlag = "uninstall "; + sizeCmdFlag = 10; // 10: cmdFlag uninstall size + } else if (CMD_UNITY_BUGREPORT_INIT == formatCommand->cmdFlag) { + cmdFlag = "bugreport "; + sizeCmdFlag = 10; // 10: cmdFlag bugreport size + } else if (CMD_APP_SIDELOAD == formatCommand->cmdFlag) { + cmdFlag = "sideload "; + sizeCmdFlag = 9; // 9: cmdFlag sideload size + } else if (CMD_UPDATER_UPDATE_INIT == formatCommand->cmdFlag) { + cmdFlag = "update "; + sizeCmdFlag = 7; // 7: cmdFlag update size + } else if (CMD_UPDATER_FLASH_INIT == formatCommand->cmdFlag) { + cmdFlag = "flash "; + sizeCmdFlag = 6; // 6: cmdFlag flash size + } + uint8_t *payload = reinterpret_cast(const_cast(formatCommand->parameters.c_str())) + sizeCmdFlag; + if (!strncmp(formatCommand->parameters.c_str(), cmdFlag.c_str(), sizeCmdFlag)) { // local do + HSession hSession = FindAliveSession(hChannel->targetSessionId); + if (!hSession) { + return false; + } + ptrServer->DispatchTaskData(hSession, hChannel->channelId, formatCommand->cmdFlag, payload, + sizeSend - sizeCmdFlag); + } else { // Send to Daemon-side to do + SendToDaemon(hChannel, formatCommand->cmdFlag, payload, sizeSend - sizeCmdFlag); + } + return true; +} + +bool HdcServerForClient::DoCommandRemote(HChannel hChannel, void *formatCommandInput) +{ + TranslateCommand::FormatCommand *formatCommand = (TranslateCommand::FormatCommand *)formatCommandInput; + bool ret = false; + int sizeSend = formatCommand->parameters.size(); + string cmdFlag; + switch (formatCommand->cmdFlag) { + // Some simple commands only need to forward the instruction, no need to start Task + case CMD_SHELL_INIT: + case CMD_SHELL_DATA: + case CMD_UNITY_EXECUTE: + case CMD_UNITY_TERMINATE: + case CMD_UNITY_REMOUNT: + case CMD_UNITY_REBOOT: + case CMD_UNITY_RUNMODE: + case CMD_UNITY_HILOG: + case CMD_UNITY_ROOTRUN: + case CMD_UNITY_JPID: { + if (!SendToDaemon(hChannel, formatCommand->cmdFlag, + reinterpret_cast(const_cast(formatCommand->parameters.c_str())), + sizeSend)) { + break; + } + ret = true; + if (CMD_SHELL_INIT == formatCommand->cmdFlag) { + hChannel->interactiveShellMode = true; + } + break; + } + case CMD_FILE_INIT: + case CMD_FORWARD_INIT: + case CMD_APP_INIT: + case CMD_APP_UNINSTALL: + case CMD_UNITY_BUGREPORT_INIT: + case CMD_APP_SIDELOAD: + case CMD_UPDATER_UPDATE_INIT: + case CMD_UPDATER_FLASH_INIT: + case CMD_UPDATER_ERASE: + case CMD_UPDATER_FORMAT: { + TaskCommand(hChannel, formatCommandInput); + ret = true; + break; + } + default: + break; + } + if (!ret) { + EchoClient(hChannel, MSG_FAIL, "Failed to communicate with daemon"); + } + return ret; +} +// Do not specify Target's operations no longer need to put it in the thread. +bool HdcServerForClient::DoCommand(HChannel hChannel, void *formatCommandInput) +{ + bool ret = false; + if (!hChannel->hChildWorkTCP.loop) { + // Main thread command, direct Listen main thread + ret = DoCommandLocal(hChannel, formatCommandInput); + } else { // CONNECT DAEMON's work thread command, non-primary thread + ret = DoCommandRemote(hChannel, formatCommandInput); + } + return ret; +} + +// just call from BindChannelToSession +HSession HdcServerForClient::FindAliveSessionFromDaemonMap(const HChannel hChannel) +{ + HSession hSession = nullptr; + HDaemonInfo hdi = nullptr; + HdcServer *ptrServer = (HdcServer *)clsServer; + ptrServer->AdminDaemonMap(OP_QUERY, hChannel->connectKey, hdi); + if (!hdi) { + EchoClient(hChannel, MSG_FAIL, "Not match target founded, check connect-key please"); + return nullptr; + } + if (hdi->connStatus != STATUS_CONNECTED) { + EchoClient(hChannel, MSG_FAIL, "Device not founded or connected"); + return nullptr; + } + if (hdi->hSession->isDead) { + EchoClient(hChannel, MSG_FAIL, "Bind tartget session is dead"); + return nullptr; + } + hSession = (HSession)hdi->hSession; + return hSession; +} + +int HdcServerForClient::BindChannelToSession(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + HSession hSession = nullptr; + if ((hSession = FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return ERR_SESSION_NOFOUND; + } + bool isClosing = uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP); + if (!isClosing && (hChannel->fdChildWorkTCP = Base::DuplicateUvSocket(&hChannel->hWorkTCP)) < 0) { + WRITE_LOG(LOG_FATAL, "Duplicate socket failed, cid:%d", hChannel->channelId); + return ERR_SOCKET_DUPLICATE; + } + uv_close_cb funcWorkTcpClose = [](uv_handle_t *handle) -> void { + HChannel hChannel = (HChannel)handle->data; + --hChannel->sendRef; + }; + ++hChannel->sendRef; + if (!isClosing) { + uv_close((uv_handle_t *)&hChannel->hWorkTCP, funcWorkTcpClose); + } + Base::DoNextLoop(loopMain, hChannel, [](const uint8_t flag, string &msg, const void *data) { + // Thread message can avoid using thread lock and improve program efficiency + // If not next loop call, ReadStream will thread conflict + HChannel hChannel = (HChannel)data; + auto thisClass = (HdcServerForClient *)hChannel->clsChannel; + HSession hSession = nullptr; + if ((hSession = thisClass->FindAliveSessionFromDaemonMap(hChannel)) == nullptr) { + return; + } + auto ctrl = HdcSessionBase::BuildCtrlString(SP_ATTACH_CHANNEL, hChannel->channelId, nullptr, 0); + Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrl.data(), ctrl.size()); + }); + return RET_SUCCESS; +} + +bool HdcServerForClient::CheckAutoFillTarget(HChannel hChannel) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + if (!hChannel->connectKey.size()) { + return false; // Operation of non-bound destination of scanning + } + if (hChannel->connectKey == CMDSTR_CONNECT_ANY) { + HDaemonInfo hdiOld = nullptr; + ptrServer->AdminDaemonMap(OP_GET_ONLY, "", hdiOld); + if (!hdiOld) { + return false; + } + hChannel->connectKey = hdiOld->connectKey; + return true; + } + return true; +} + +int HdcServerForClient::ChannelHandShake(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + vector rebuildHandshake; + rebuildHandshake.insert(rebuildHandshake.end(), bufPtr, bufPtr + bytesIO); + rebuildHandshake.push_back(0x00); + struct ChannelHandShake *handShake = reinterpret_cast(rebuildHandshake.data()); + if (strncmp(handShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Channel Hello failed"); + return ERR_HANDSHAKE_NOTMATCH; + } + if (strlen(handShake->connectKey) > sizeof(handShake->connectKey)) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_DEBUG, "Connectkey's size incorrect"); + return ERR_HANDSHAKE_CONNECTKEY_FAILED; + } + // channel handshake step3 + WRITE_LOG(LOG_DEBUG, "ServerForClient channel handshake finished"); + hChannel->connectKey = handShake->connectKey; + hChannel->handshakeOK = true; + if (!CheckAutoFillTarget(hChannel)) { + return 0; + } + // channel handshake stBindChannelToSession + if (BindChannelToSession(hChannel, nullptr, 0)) { + hChannel->availTailIndex = 0; + WRITE_LOG(LOG_FATAL, "BindChannelToSession failed"); + return ERR_GENERIC; + } + return 0; +} + +// Here is Server to get data, the source is the SERVER's ChildWork to send data +int HdcServerForClient::ReadChannel(HChannel hChannel, uint8_t *bufPtr, const int bytesIO) +{ + int ret = 0; + if (!hChannel->handshakeOK) { + return ChannelHandShake(hChannel, bufPtr, bytesIO); + } + struct TranslateCommand::FormatCommand formatCommand = { 0 }; + if (!hChannel->interactiveShellMode) { + string retEcho = String2FormatCommand((char *)bufPtr, bytesIO, &formatCommand); + if (retEcho.length()) { + if (!strcmp((char *)bufPtr, CMDSTR_SOFTWARE_HELP.c_str()) || + !strcmp((char *)bufPtr, CMDSTR_SOFTWARE_VERSION.c_str()) || + !strcmp((char *)bufPtr, "flash")) { + EchoClient(hChannel, MSG_OK, retEcho.c_str()); + } else { + EchoClient(hChannel, MSG_FAIL, retEcho.c_str()); + } + } + if (formatCommand.bJumpDo) { + ret = -10; // 10 error code + return ret; + } + } else { + formatCommand.parameters = string(reinterpret_cast(bufPtr), bytesIO); + formatCommand.cmdFlag = CMD_SHELL_DATA; + } + if (!DoCommand(hChannel, &formatCommand)) { + return -3; // -3: error or want close + } + ret = bytesIO; + return ret; +}; + +// avoid session dead +HSession HdcServerForClient::FindAliveSession(uint32_t sessionId) +{ + HdcServer *ptrServer = (HdcServer *)clsServer; + HSession hSession = ptrServer->AdminSession(OP_QUERY, sessionId, nullptr); + if (!hSession || hSession->isDead) { + return nullptr; + } else { + return hSession; + } +} + +bool HdcServerForClient::ChannelSendSessionCtrlMsg(vector &ctrlMsg, uint32_t sessionId) +{ + HSession hSession = FindAliveSession(sessionId); + if (!hSession) { + return false; + } + return Base::SendToStream((uv_stream_t *)&hSession->ctrlPipe[STREAM_MAIN], ctrlMsg.data(), ctrlMsg.size()) > 0; +} +} // namespace Hdc diff --git a/services/flashd/host/translate.cpp b/services/flashd/host/translate.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5b274307af359d602252b482a2080fc2836565ec --- /dev/null +++ b/services/flashd/host/translate.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "translate.h" +#include "host_updater.h" + +namespace Hdc { +namespace TranslateCommand { + string Usage() + { + string ret; + + ret = "\n OpenHarmony flash ...\n\n" + "---------------------------------global commands:----------------------------------\n" + " -h/help - Print flashd help\n" + " -v/version - Print flashd version\n" + " -l 0-5 - Set runtime loglevel\n" + " -t connectkey - Use device with given connect key\n" + "\n" + "---------------------------------component commands:-------------------------------\n" + "session commands(on server):\n" + " discover - Discover devices listening on TCP via LAN broadcast\n" + " list targets [-v] - List all devices status, -v for detail\n" + " tconn key - Connect device via key, TCP use ip:port\n" + " example:192.168.0.100:10178/192.168.0.100\n" + " USB connect automatic, TCP need to connect manually\n" + " start [-r] - Start server. If with '-r', will be restart server\n" + " kill [-r] - Kill server. If with '-r', will be restart server\n" + " -s [ip:]port - Set flash server listen config\n" + "\n" + "service commands(on daemon):\n" + " target boot [-bootloader|-recovery] - Reboot the device or boot into bootloader\\recovery.\n" + " tmode usb - Reboot the device, listening on USB\n" + " tmode port [port] - Reboot the device, listening on TCP port\n" + "\n" + "---------------------------------flash commands:-------------------------------------\n" + "flash commands:\n" + " update packagename - Update system by package\n" + " flash [-f] partition imagename - Flash partition by image\n" + " erase [-f] partition - Erase partition\n" + " format [-f] partition -t fs_type - Format partition -t [ext4 | f2fs]\n"; + return ret; + } + + string TargetConnect(FormatCommand *outCmd) + { + string stringError; + if (Base::StringEndsWith(outCmd->parameters, " -remove")) { + outCmd->parameters = outCmd->parameters.substr(0, outCmd->parameters.size() - 8); // 8 leng + outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCONNECT; + } else { + outCmd->cmdFlag = CMD_KERNEL_TARGET_CONNECT; + if (outCmd->parameters.size() > 22) { // 22: tcp max=21,USB max=8bytes + stringError = "Error connect key's size"; + outCmd->bJumpDo = true; + } + } + if (outCmd->parameters.find(":") != std::string::npos) { + // tcp mode + string ip = outCmd->parameters.substr(0, outCmd->parameters.find(":")); + string sport = outCmd->parameters.substr(outCmd->parameters.find(":") + 1); + int port = std::stoi(sport); + sockaddr_in addr; + if ((port <= 0 || port > MAX_IP_PORT) || uv_ip4_addr(ip.c_str(), port, &addr) < 0) { + stringError = "IP:Port incorrect"; + outCmd->bJumpDo = true; + } + } + return stringError; + } + + string ForwardPort(const char *input, FormatCommand *outCmd) + { + string stringError; + const char *pExtra = input + 6; // CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT + " " size + if (!strcmp(pExtra, "ls")) { + outCmd->cmdFlag = CMD_FORWARD_LIST; + } else if (!strncmp(pExtra, "rm", 2)) { // 2 rm size + outCmd->cmdFlag = CMD_FORWARD_REMOVE; + if (strcmp(pExtra, "rm")) { + outCmd->parameters = input + 9; // 9 rm extra size + } + } else { + const char *p = input + 6; // 6 length + // clang-format off + if (strncmp(p, "tcp:", 4) && // 4 legnth of tcp + strncmp(p, "localabstract:", 14) && // 14 legnth of localabstract + strncmp(p, "localreserved:", 14) && // 14 legnth of localreserved + strncmp(p, "localfilesystem:", 16) && // 14 legnth of localfilesystem + strncmp(p, "dev:", 4) && // 4 legnth of dev + strncmp(p, "jdwp:", 5)) { // 14 legnth of jdwp + stringError = "Incorrect forward command"; + outCmd->bJumpDo = true; + } + // clang-format on + outCmd->cmdFlag = CMD_FORWARD_INIT; + outCmd->parameters = input; + } + return stringError; + } + + string RunMode(const char *input, FormatCommand *outCmd) + { + string stringError; + outCmd->cmdFlag = CMD_UNITY_RUNMODE; + outCmd->parameters = input + CMDSTR_TARGET_MODE.size() + 1; // with ' ' + if (!strncmp(outCmd->parameters.c_str(), "port", 4) // 4 port len + && !strcmp(outCmd->parameters.c_str(), CMDSTR_TMODE_USB.c_str())) { + stringError = "Error tmode command"; + outCmd->bJumpDo = true; + } else if (!strncmp(outCmd->parameters.c_str(), "port ", 5)) { // 5 port len + int port = atoi(input + 4); // 4 port len + if (port > MAX_IP_PORT || port <= 0) { + stringError = "Incorrect port range"; + outCmd->bJumpDo = true; + } + } + return stringError; + } + + string TargetReboot(const char *input, FormatCommand *outCmd) + { + string stringError; + outCmd->cmdFlag = CMD_UNITY_REBOOT; + if (strcmp(input, CMDSTR_TARGET_REBOOT.c_str())) { + outCmd->parameters = input + 12; // 12 length of target boot + if (outCmd->parameters != "-bootloader" + && outCmd->parameters != "-recovery" && outCmd->parameters != "-flashd") { + stringError = "Error reboot paramenter"; + outCmd->bJumpDo = true; + } else { + outCmd->parameters.erase(outCmd->parameters.begin()); + } + } + return stringError; + } + + // command input + // client side:Enter string data formatting conversion to module see internal processing command + string String2FormatCommand(const char *inputRaw, int sizeInputRaw, FormatCommand *outCmd) + { + string stringError; + string input = string(inputRaw, sizeInputRaw); + if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_HELP.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_HELP; + stringError = Usage(); + outCmd->bJumpDo = true; + } else if (!strcmp(input.c_str(), CMDSTR_SOFTWARE_VERSION.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_HELP; + stringError = Base::GetVersion(); + outCmd->bJumpDo = true; + } else if (!strcmp(input.c_str(), CMDSTR_TARGET_DISCOVER.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_DISCOVER; + } else if (!strncmp(input.c_str(), CMDSTR_LIST_TARGETS.c_str(), CMDSTR_LIST_TARGETS.size())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_LIST; + if (strstr(input.c_str(), " -v")) { + outCmd->parameters = "v"; + } + } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; + } else if (!strncmp(input.c_str(), CMDSTR_CONNECT_TARGET.c_str(), CMDSTR_CONNECT_TARGET.size())) { + outCmd->parameters = input.c_str() + CMDSTR_CONNECT_TARGET.size() + 1; // with ' ' + stringError = TargetConnect(outCmd); + } else if (!strncmp(input.c_str(), (CMDSTR_SHELL + " ").c_str(), CMDSTR_SHELL.size() + 1)) { + outCmd->cmdFlag = CMD_UNITY_EXECUTE; + outCmd->parameters = input.c_str() + CMDSTR_SHELL.size() + 1; + } else if (!strcmp(input.c_str(), CMDSTR_SHELL.c_str())) { + outCmd->cmdFlag = CMD_SHELL_INIT; + } else if (!strncmp(input.c_str(), CMDSTR_FILE_SEND.c_str(), CMDSTR_FILE_SEND.size()) + || !strncmp(input.c_str(), CMDSTR_FILE_RECV.c_str(), CMDSTR_FILE_RECV.size())) { + outCmd->cmdFlag = CMD_FILE_INIT; + outCmd->parameters = input.c_str() + 5; // 5: CMDSTR_FORWARD_FPORT CMDSTR_FORWARD_RPORT size + } else if (!strncmp(input.c_str(), string(CMDSTR_FORWARD_FPORT + " ").c_str(), CMDSTR_FORWARD_FPORT.size() + 1) + || !strncmp(input.c_str(), string(CMDSTR_FORWARD_RPORT + " ").c_str(), + CMDSTR_FORWARD_RPORT.size() + 1)) { + stringError = ForwardPort(input.c_str(), outCmd); + } else if (!strcmp(input.c_str(), CMDSTR_KILL_SERVER.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_SERVER_KILL; + } else if (!strcmp(input.c_str(), CMDSTR_KILL_DAEMON.c_str())) { + outCmd->cmdFlag = CMD_UNITY_TERMINATE; + outCmd->parameters = "0"; + } else if (!strncmp(input.c_str(), CMDSTR_APP_INSTALL.c_str(), CMDSTR_APP_INSTALL.size())) { + outCmd->cmdFlag = CMD_APP_INIT; + outCmd->parameters = input; + } else if (!strncmp(input.c_str(), CMDSTR_APP_UNINSTALL.c_str(), CMDSTR_APP_UNINSTALL.size())) { + outCmd->cmdFlag = CMD_APP_UNINSTALL; + outCmd->parameters = input; + if (outCmd->parameters.size() > 512 || outCmd->parameters.size() < 4) { // 512 4 max and min name length + stringError = "Package's path incorrect"; + outCmd->bJumpDo = true; + } + } else if (!strcmp(input.c_str(), CMDSTR_TARGET_MOUNT.c_str())) { + outCmd->cmdFlag = CMD_UNITY_REMOUNT; + } else if (!strcmp(input.c_str(), CMDSTR_LIST_JDWP.c_str())) { + outCmd->cmdFlag = CMD_UNITY_JPID; + } else if (!strncmp(input.c_str(), CMDSTR_TARGET_REBOOT.c_str(), CMDSTR_TARGET_REBOOT.size())) { + TargetReboot(input.c_str(), outCmd); + } else if (!strncmp(input.c_str(), CMDSTR_TARGET_MODE.c_str(), CMDSTR_TARGET_MODE.size())) { + RunMode(input.c_str(), outCmd); + } else if (!strcmp(input.c_str(), CMDSTR_CONNECT_ANY.c_str())) { + outCmd->cmdFlag = CMD_KERNEL_TARGET_ANY; + } else if (!strncmp(input.c_str(), CMDSTR_HILOG.c_str(), CMDSTR_HILOG.size())) { + outCmd->cmdFlag = CMD_UNITY_HILOG; + if (strstr(input.c_str(), " -v")) { + outCmd->parameters = "v"; + } + } else if (!strncmp(input.c_str(), CMDSTR_STARTUP_MODE.c_str(), CMDSTR_STARTUP_MODE.size())) { + outCmd->cmdFlag = CMD_UNITY_ROOTRUN; + if (strstr(input.c_str(), " -r")) { + outCmd->parameters = "r"; + } + } else if (!strncmp(input.c_str(), CMDSTR_APP_SIDELOAD.c_str(), CMDSTR_APP_SIDELOAD.size())) { + if (strlen(input.c_str()) == CMDSTR_APP_SIDELOAD.size()) { + stringError = "Incorrect command, please with local path"; + outCmd->bJumpDo = true; + } + outCmd->cmdFlag = CMD_APP_SIDELOAD; + outCmd->parameters = input; + } else if (!strncmp(input.c_str(), CMDSTR_BUGREPORT.c_str(), CMDSTR_BUGREPORT.size())) { + outCmd->cmdFlag = CMD_UNITY_BUGREPORT_INIT; + outCmd->parameters = input; + if (outCmd->parameters.size() == CMDSTR_BUGREPORT.size()) { + outCmd->parameters += " "; + } + } else if (input == CMDSTR_INNER_ENABLE_KEEPALIVE) { // Inner command, protocol uses only + outCmd->cmdFlag = CMD_KERNEL_ENABLE_KEEPALIVE; + } else if (HostUpdater::CheckMatchUpdate(input, stringError, outCmd->cmdFlag, outCmd->bJumpDo)) { + outCmd->parameters = input; + } else { + stringError = "Unknown command..."; + outCmd->bJumpDo = true; + } + // nl + if (stringError.size()) { + stringError += "\n"; + } + return stringError; + }; +} +} // namespace Hdc diff --git a/services/flashd/partition.cpp b/services/flashd/partition.cpp index 75d0f1d87b9859b844c48489bb00c8510f9d0159..aa4264f08f0ee4711600a006c11a2084bc322227 100755 --- a/services/flashd/partition.cpp +++ b/services/flashd/partition.cpp @@ -106,12 +106,16 @@ int Partition::DoErase() if (ret < 0) { range[0] = 0; range[1] = size; +#ifndef UPDATER_UT ret = ioctl(fd_, BLKDISCARD, &range); +#endif FLASHING_CHECK(ret >= 0, flash_->RecordMsg(updater::ERROR, "Failed to erase \"%s\" error: %s", partName_.c_str(), strerror(errno)); return ret, "Failed to erase %s error: %s", partName_.c_str(), strerror(errno)); std::vector buffer(BLOCK_SIZE, 0); +#ifndef UPDATER_UT ret = updater::utils::WriteFully(fd_, buffer.data(), buffer.size()); +#endif FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to flash data errno %d", errno); fsync(fd_); } @@ -121,11 +125,9 @@ int Partition::DoErase() int Partition::DoFormat(const std::string &fsType) { - if (mountPoint_ == "/") { /* Can not format root */ - return 0; - } int ret = DoUmount(); FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to umount partition"); + FLASHING_LOGI("DoFormat partition %s format %s", partName_.c_str(), fsType_.c_str()); std::vector formatCmds {}; ret = BuildCommandParam(fsType, formatCmds); @@ -150,15 +152,6 @@ int Partition::DoResize(uint32_t blocks) bool needResize = false; if (!mountPoint_.empty()) { needResize = FlashService::CheckFreeSpace(mountPoint_, blocks); - } else { - ret = Open(); - FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for erase", partName_.c_str()); - uint64_t size = GetBlockDeviceSize(fd_); - FLASHING_LOGI("DoResise partition %s size %lu", partName_.c_str(), size); - close(fd_); - fd_ = -1; - uint64_t min = static_cast(DEFAULT_BLOCK_SIZE) * static_cast(blocks); - needResize = size < min; } if (!needResize) { FLASHING_LOGI("No need to resize partition %s", partName_.c_str()); @@ -184,10 +177,9 @@ int Partition::DoResize(uint32_t blocks) int Partition::Open() { - if (fd_ != -1) { - return 0; + if (fd_ <= 0) { + fd_ = open(partPath_.c_str(), O_RDWR); } - fd_ = open(partPath_.c_str(), O_RDWR); FLASHING_CHECK(fd_ > 0, flash_->RecordMsg(updater::ERROR, "Can not open partiton \"%s\" error: %s", partName_.c_str(), strerror(errno)); @@ -211,12 +203,9 @@ int Partition::WriteRowData(int inputFd, size_t fileSize, std::vector & totalWrite += writeLen; // continue read and write - ssize_t ret = read(inputFd, buffer.data(), buffer.size()); - if (ret <= 0) { - break; - } - - flash_->PostProgress(UPDATEMOD_FLASH, dataSize, nullptr); + ssize_t ret = read(inputFd, buffer.data(), dataSize); + FLASHING_CHECK(ret > 0, return -1, "Failed to read data %d %d", errno, buffer.size()); + flash_->PostProgress(UPDATEMOD_FLASH, writeLen, nullptr); dataLen = ret; } while (1); fsync(fd_); @@ -227,9 +216,7 @@ int Partition::IsBlockDevice(int fd) const { struct stat st {}; int ret = fstat(fd, &st); - if (ret < 0) { - return 0; - } + FLASHING_CHECK(ret >= 0, return 0, "Invalid get fstate %d", errno); return S_ISBLK(st.st_mode); } @@ -299,11 +286,13 @@ int Partition::DoUmount() if (mountPoint_.empty()) { return 0; } +#ifndef UPDATER_UT int ret = umount2(mountPoint_.c_str(), MNT_FORCE); FLASHING_CHECK(ret == 0, flash_->RecordMsg(updater::ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); return FLASHING_PART_WRITE_ERROR, "Failed to umount \"%s\" error: %s", partName_.c_str(), strerror(errno)); - return ret; +#endif + return 0; } int Partition::DoMount() @@ -324,7 +313,11 @@ int Partition::DoMount() std::string data; uint32_t flags = GetMountFlags(mountFlags_, data); errno = 0; + while ((ret = mount(partPath_.c_str(), mountPoint_.c_str(), fsType_.c_str(), flags, data.c_str()) != 0)) { +#ifdef UPDATER_UT + ret = 0; +#endif if (errno == EAGAIN) { continue; } else { diff --git a/services/include/flashd/flashd.h b/services/include/flashd/flashd.h index 8eae9598f7bbea27dc0606926051c8499e0052b2..13af85572eead70ec00cf46f3fe7789310ea1213 100755 --- a/services/include/flashd/flashd.h +++ b/services/include/flashd/flashd.h @@ -44,21 +44,19 @@ static constexpr uint16_t MAX_SIZE_BUF = 1024; static constexpr uint32_t PERCENT_FINISH = 100; static constexpr uint32_t PERCENT_CLEAR = (uint32_t)-1; -#ifndef LOCAL_SUPPORT const std::string FORMAT_TOOL_FOR_EXT4 = "/bin/mke2fs"; const std::string FORMAT_TOOL_FOR_F2FS = "/bin/make_f2fs"; const std::string RESIZE_TOOL = "/bin/resize2fs"; + +#ifndef UPDATER_UT const std::string FLASHD_FILE_PATH = "/data/updater/"; const std::string FLASHD_HDC_LOG_PATH = "/tmp/flashd_hdc.log"; #else -const std::string FORMAT_TOOL_FOR_EXT4 = "/usr/sbin/mke2fs"; -const std::string FORMAT_TOOL_FOR_F2FS = "/system/bin/make_f2fs"; -const std::string RESIZE_TOOL = "/bin/resize2fs"; -const std::string FLASHD_FILE_PATH = "/home/axw/develop/build/"; -const std::string FLASHD_HDC_LOG_PATH = "/home/axw/develop/build/hdc.log"; +const std::string FLASHD_FILE_PATH = "/data/updater/updater/"; +const std::string FLASHD_HDC_LOG_PATH = "/data/updater/flashd_hdc.log"; #endif static constexpr uint32_t MIN_BLOCKS_FOR_UPDATE = 1024 * 1024; -static constexpr uint32_t DEFAULT_BLOCK_SIZE = 4096; +static constexpr uint32_t DEFAULT_BLOCK_SIZE = 2048; static constexpr uint32_t DEFAULT_SIZE_UNIT = 1024 * 1024; using FlashHandle = void *; @@ -69,5 +67,17 @@ int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunc int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath); int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath); int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition); + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +int SetParameter(const char *key, const char *value); +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif } // namespace flashd #endif /* UPDATER_FLASHING_H */ diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index 0d94c5ab7e95dd1103bcd4ada4cbcad58f0858fd..272c301ac6afab32d28b9a1248a090306bf164e9 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -52,8 +52,10 @@ int IsSpaceCapacitySufficient(const std::string &packagePath); bool IsSDCardExist(const std::string &sdcard_path); -void PostUpdater(); +void PostUpdater(bool clearMisc); std::vector ParseParams(int argc, char **argv); + +int GetBootMode(int &mode); } // updater #endif /* UPDATER_UPDATER_H */ diff --git a/services/include/updater/updater_const.h b/services/include/updater/updater_const.h index 88775927d246b12bb3ee59cc43e305ffbde023f3..6b447687201e76eb889baabf32d68f4300f15302 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -75,5 +75,7 @@ constexpr unsigned int UI_SHOW_DURATION = 2000; constexpr unsigned int INTERVAL_TIME = 300; constexpr float EPSINON = 0.00001; constexpr float FULL_EPSINON = 1; +constexpr int BOOT_FLASHD = 1; +constexpr int BOOT_UPDATER = 2; } // namespace updater #endif diff --git a/services/main.cpp b/services/main.cpp index bb29543ff4619be6fe69489577fc2fcb7f975d11..d6a5e6da14635e7e8727dbab2ca1fe4cff467176 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -13,6 +13,8 @@ * limitations under the License. */ #include "fs_manager/mount.h" +#include "fs_manager/fs_manager_log.h" +#include "flashd/flashd.h" #include "log/log.h" #include "misc_info/misc_info.h" #include "updater/updater_const.h" @@ -22,27 +24,20 @@ using namespace updater; int main(int argc, char **argv) { - struct UpdateMessage boot {}; - // read from misc - bool ret = ReadUpdaterMessage(MISC_FILE, boot); - if (!ret) { - printf("ReadUpdaterMessage MISC_FILE failed!\n"); + int mode = BOOT_UPDATER; + int ret = GetBootMode(mode); + if (ret != 0) { + printf("Failed to get boot mode, start updater mode \n"); + mode = BOOT_UPDATER; } - // if boot.update is empty, read from command.The Misc partition may have dirty data, - // so strlen(boot.update) is not used, which can cause system exceptions. - if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { - ret = ReadUpdaterMessage(COMMAND_FILE, boot); - if (!ret) { - printf("ReadUpdaterMessage COMMAND_FILE failed!\n"); - } - } - const int flashBootLength = 10; - bool useFlash = memcmp(boot.command, "boot_flash", flashBootLength) == 0; - InitUpdaterLogger(useFlash ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); + + InitUpdaterLogger((mode == BOOT_FLASHD) ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); SetLogLevel(INFO); + FsManagerLogInit(LOG_TO_FILE, TMP_LOG.c_str()); LoadFstab(); - STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; - LOG(INFO) << "boot.command " << boot.command; - LOG(INFO) << "boot.update " << boot.update; + STAGE(UPDATE_STAGE_OUT) << "Start " << ((mode == BOOT_FLASHD) ? "flashd" : "updater"); + if (mode == BOOT_FLASHD) { + return flashd::flashd_main(argc, argv); + } return updater::UpdaterMain(argc, argv); } diff --git a/services/package/pkg_algorithm/pkg_algo_digest.cpp b/services/package/pkg_algorithm/pkg_algo_digest.cpp index 1855aa675b9978b88673b6641b7b943010f4ba49..0c1b89343d2d09d6498690d7168a0605df5080f1 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.cpp +++ b/services/package/pkg_algorithm/pkg_algo_digest.cpp @@ -39,7 +39,11 @@ size_t DigestAlgorithm::GetSignatureLen(int8_t digestMethod) uint8_t DigestAlgorithm::GetDigestMethod(std::string version) { - return PKG_DIGEST_TYPE_SHA256; + if (version == "3") { + return PKG_DIGEST_TYPE_SHA384; + } else { + return PKG_DIGEST_TYPE_SHA256; + } } int32_t Crc32Algorithm::Init() @@ -120,7 +124,7 @@ int32_t Sha384Algorithm::Update(const PkgBuffer &buffer, size_t size) int32_t Sha384Algorithm::Final(PkgBuffer &result) { - PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, + PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length return PKG_INVALID_PARAM, "Param context null!"); SHA384_Final(result.buffer, &shaCtx_); return PKG_SUCCESS; @@ -128,7 +132,7 @@ int32_t Sha384Algorithm::Final(PkgBuffer &result) int32_t Sha384Algorithm::Calculate(PkgBuffer &result, const PkgBuffer &buffer, size_t size) { - PKG_CHECK(result.buffer != nullptr && result.length == DIGEST_SHA384_LEN, + PKG_CHECK(result.buffer != nullptr && result.length == 64, // 64 length return PKG_INVALID_PARAM, "Param context null!"); PKG_CHECK(buffer.buffer != nullptr, return PKG_INVALID_PARAM, "Param null!"); SHA512_Init(&shaCtx_); diff --git a/services/package/pkg_algorithm/pkg_algo_digest.h b/services/package/pkg_algorithm/pkg_algo_digest.h index 4b08139dda2df4e43109f57d133d98fd2b6b56cb..a83c1328953179252cdb55bae1e7c31142d58597 100644 --- a/services/package/pkg_algorithm/pkg_algo_digest.h +++ b/services/package/pkg_algorithm/pkg_algo_digest.h @@ -21,7 +21,7 @@ namespace hpackage { constexpr uint32_t DIGEST_CRC_LEN = 4; constexpr uint32_t DIGEST_SHA256_LEN = 32; -constexpr uint32_t DIGEST_SHA384_LEN = 64; +constexpr uint32_t DIGEST_SHA384_LEN = 48; constexpr uint32_t SIGN_SHA256_LEN = 256; constexpr uint32_t SIGN_SHA384_LEN = 384; constexpr uint32_t SIGN_TOTAL_LEN = 384 + 256; diff --git a/services/package/pkg_algorithm/pkg_algo_sign.cpp b/services/package/pkg_algorithm/pkg_algo_sign.cpp index fd258ded38c3e2eea8bd0a968582920d540e6c44..b0f9d9cc57be7dc5841ea19c96472edf312e0ed7 100644 --- a/services/package/pkg_algorithm/pkg_algo_sign.cpp +++ b/services/package/pkg_algorithm/pkg_algo_sign.cpp @@ -85,14 +85,20 @@ int32_t SignAlgorithmEcc::SignBuffer(const PkgBuffer &buffer, std::vector &digest, const int hashNid = NID_sha1; if (certs.hashLen == SHA256_DIGEST_LENGTH) { hashNid = NID_sha256; + } else if (certs.hashLen == SHA384_DIGEST_LENGTH) { + hashNid = NID_sha384; } int ret = 0; if (certs.keyType == KEY_TYPE_RSA) { diff --git a/services/package/pkg_algorithm/pkg_algo_sign.h b/services/package/pkg_algorithm/pkg_algo_sign.h index eb0900fdd4396d94cc5d0ef672cf0dfa6194ebce..f8c6a68c63ddcca604e2078928d8358045852975 100644 --- a/services/package/pkg_algorithm/pkg_algo_sign.h +++ b/services/package/pkg_algorithm/pkg_algo_sign.h @@ -75,7 +75,7 @@ public: private: bool CheckEccKey(const EC_KEY *eccKey) const; - bool CheckRsaKey(const RSA *rsakey) const; + bool CheckRsaKey(const RSA *rsakey, int &hashLen) const; bool LoadPubKey(const std::string &filename, struct CertKeySt &certs) const; }; diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index 684536c001770598badf1d0aadddddce7801f5a2..aa8951571be69499d6925c0952d3113476ce4e2c 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -104,6 +104,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; @@ -120,6 +121,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; @@ -136,6 +138,7 @@ int32_t PkgManagerImpl::CreatePackage(const std::string &path, const std::string if (pkgFile == nullptr) { return PKG_INVALID_FILE; } + offset = (header->digestMethod == PKG_DIGEST_TYPE_SHA384) ? (offset + SIGN_SHA256_LEN) : offset; ret = Sign(pkgFile->GetPkgStream(), offset, header); delete pkgFile; return ret; diff --git a/services/package/pkg_package/pkg_lz4file.cpp b/services/package/pkg_package/pkg_lz4file.cpp index 372c9cdc688f03a9df537b3b4f2aefda82ec1717..96d8f4caf4700c9d448d9bacc5b42dae631fecf8 100644 --- a/services/package/pkg_package/pkg_lz4file.cpp +++ b/services/package/pkg_package/pkg_lz4file.cpp @@ -130,7 +130,6 @@ int32_t Lz4PkgFile::AddEntry(const PkgManager::FileInfoPtr file, const PkgStream PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Pack for %s", file->identity.c_str()); currentOffset_ += encodeLen; PKG_LOGI("offset:%zu ", currentOffset_); - pkgStream_->Flush(currentOffset_); return PKG_SUCCESS; } diff --git a/services/ui/updater_ui.cpp b/services/ui/updater_ui.cpp index bf15c482c32e7bd7c3f20655603979b0ff5cc02b..edcbc93cfad0d70c7d6fdc1b8a76a62b76772565 100644 --- a/services/ui/updater_ui.cpp +++ b/services/ui/updater_ui.cpp @@ -162,7 +162,7 @@ void OnKeyEvent(int viewId) ClearText(); if (viewId == g_textLabel0->GetViewId() && g_textLabel0->IsVisiable()) { HideDialog(); - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); } else if (viewId == g_textLabel2->GetViewId() && g_textLabel2->IsVisiable()) { ShowDialog(); @@ -174,7 +174,7 @@ void OnKeyEvent(int viewId) ShowMenu(); return; } - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); } else if (viewId == g_dialogCancalBtn->GetViewId() && g_dialogCancalBtn->IsVisiable()) { HideDialog(); @@ -439,6 +439,7 @@ void UpdaterUiInit() g_anmimationLabel->SetBackgroundColor(&bgColor); LoadImgs(); g_progressBar = new ProgressBar(START_X3, START_Y3, WIDTH3, HEIGHT3, g_updateFrame); + g_progressBar->Hide(); g_updateInfoLabel = new TextLabel(START_X5, START_Y5, screenW, HEIGHT5, g_updateFrame); g_updateInfoLabel->SetOutLineBold(false, false); diff --git a/services/updater.cpp b/services/updater.cpp index caccbbfe39d841618be47c379fb5202e199047dc..3aa34d7466ef35e69d5b6d67960fefc21e64c5fe 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -153,9 +153,7 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons // Only handle UPATE_ERROR and UPDATE_SUCCESS here. // If it returns UPDATE_CORRUPT, which means something wrong with package manager. // Let package verify handle this. - if (ret == UPDATE_SPACE_NOTENOUGH) { - ShowText(GetUpdateInfoLabel(), "Free space is not enough"); - } else if (ret == UPDATE_ERROR) { + if (ret == UPDATE_SPACE_NOTENOUGH || ret == UPDATE_ERROR) { return ret; } else if (ret == UPDATE_SUCCESS) { pkgManager = PkgManager::GetPackageInstance(); diff --git a/services/updater_binary/main.cpp b/services/updater_binary/main.cpp index 775c17c145fe1dc27708c6868f179161effdadb2..10ccdd899738604242902dc7a7c63cfa0f67d747 100644 --- a/services/updater_binary/main.cpp +++ b/services/updater_binary/main.cpp @@ -18,6 +18,7 @@ #include #include #include "fs_manager/mount.h" +#include "fs_manager/fs_manager_log.h" #include "log.h" #include "updater/updater_const.h" #include "update_processor.h" @@ -32,7 +33,7 @@ int main(int argc, char **argv) LOG(ERROR) << "Invalid arguments."; return EXIT_INVALID_ARGS; } - + FsManagerLogInit(LOG_TO_FILE, TMP_LOG.c_str()); bool retry = false; int pipeFd = static_cast(std::strtol(argv[1], nullptr, DECIMAL)); if (argc >= BINARY_MAX_ARGS && strcmp(argv[BINARY_SECOND_ARG], "retry") == 0) { @@ -43,4 +44,4 @@ int main(int argc, char **argv) std::string packagePath = argv[0]; return ProcessUpdater(retry, pipeFd, packagePath, utils::GetCertName()); } -#endif \ No newline at end of file +#endif diff --git a/services/updater_main.cpp b/services/updater_main.cpp index c4b40a2c0080efad9bd89f21ff8c9b4540bb0858..9b393a6d3f2354c575c7d419565461fb553ad043 100644 --- a/services/updater_main.cpp +++ b/services/updater_main.cpp @@ -170,7 +170,8 @@ static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::v status = DoInstallUpdaterPackage(manager, upParams.updatePackage, upParams.retryCount); if (status != UPDATE_SUCCESS) { std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); - g_logLabel->SetText("update failed!"); + std::string errMsg = ((status == UPDATE_SPACE_NOTENOUGH) ? "Free space is not enough" : "Update failed!"); + g_logLabel->SetText(errMsg.c_str()); STAGE(UPDATE_STAGE_FAIL) << "Install failed"; if (status == UPDATE_RETRY && upParams.retryCount < MAX_RETRY_COUNT) { upParams.retryCount += 1; @@ -222,7 +223,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, g_logResultLabel->SetText("Wipe data failed"); } else { g_logResultLabel->SetText("Wipe data finished"); - PostUpdater(); + PostUpdater(true); std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); } } @@ -297,7 +298,7 @@ int UpdaterMain(int argc, char **argv) return 0; } #endif - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); return 0; } diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp index 0abd3ca1371dd663912b35e4b32ad3deae787a50..bd4e7927f474066838746bb312671628bce2389b 100755 --- a/services/updater_utils.cpp +++ b/services/updater_utils.cpp @@ -196,7 +196,7 @@ void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath return; } -void PostUpdater() +void PostUpdater(bool clearMisc) { STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; std::string updaterLogPath = "/data/updater/log/updater_log"; @@ -204,7 +204,9 @@ void PostUpdater() std::string errorCodePath = "/data/updater/log/error_code.log"; PostUpdaterForSdcard(updaterLogPath, stageLogPath, errorCodePath); // clear update misc partition. - UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); + if (clearMisc) { + UPDATER_ERROR_CHECK_NOT_RETURN(ClearMisc() == true, "PostUpdater clear misc failed"); + } if (!access(COMMAND_FILE.c_str(), 0)) { UPDATER_ERROR_CHECK_NOT_RETURN(unlink(COMMAND_FILE.c_str()) == 0, "Delete command failed"); } @@ -287,4 +289,31 @@ std::vector ParseParams(int argc, char **argv) parseParams.insert(parseParams.end(), parseParams1.begin(), parseParams1.end()); return parseParams; } + +int GetBootMode(int &mode) +{ +#ifndef UPDATER_UT + mode = BOOT_UPDATER; +#else + mode = BOOT_FLASHD; +#endif + struct UpdateMessage boot {}; + // read from misc + bool ret = ReadUpdaterMessage(MISC_FILE, boot); + if (!ret) { + return -1; + } + // if boot.update is empty, read from command.The Misc partition may have dirty data, + // so strlen(boot.update) is not used, which can cause system exceptions. + if (boot.update[0] == '\0' && !access(COMMAND_FILE.c_str(), 0)) { + ret = ReadUpdaterMessage(COMMAND_FILE, boot); + if (!ret) { + return -1; + } + } + if (memcmp(boot.command, "boot_flash", strlen("boot_flash")) == 0) { + mode = BOOT_FLASHD; + } + return 0; +} } // namespace updater diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 14ec0f0f76df2dd7b3eb2cb0c66a7fe09351aa5c..5ad65418d467fa8b3d9fd1428e7f515fc16d9a63 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -44,6 +44,8 @@ ohos_unittest("updater_unittest") { "applypatch_test/transfer_manager_unittest.cpp", "diffpatch/bzip2_unittest.cpp", "diffpatch/diffpatch_unittest.cpp", + "flashd_test/flash_host_unittest.cpp", + "flashd_test/flash_service_unittest.cpp", "fs_manager/do_partition_unittest.cpp", "log_test/log_unittest.cpp", "misc_info_test/misc_info_unittest.cpp", @@ -91,6 +93,12 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/patch/blocks_patch.cpp", "//base/update/updater/services/diffpatch/patch/image_patch.cpp", "//base/update/updater/services/diffpatch/patch/update_patch.cpp", + "//base/update/updater/services/flashd/blockdevice.cpp", + "//base/update/updater/services/flashd/daemon/daemon_updater.cpp", + "//base/update/updater/services/flashd/daemon/flashd_main.cpp", + "//base/update/updater/services/flashd/flash_service.cpp", + "//base/update/updater/services/flashd/host/host_updater.cpp", + "//base/update/updater/services/flashd/partition.cpp", "//base/update/updater/services/fs_manager/cmp_partition.cpp", "//base/update/updater/services/fs_manager/do_partition.cpp", "//base/update/updater/services/fs_manager/mount.cpp", @@ -156,6 +164,10 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/package/pkg_package", "//base/update/updater/services/updater_binary", "//base/update/updater/services/include/fs_manager", + "//base/update/updater/services/flashd", + "//base/update/updater/services/flashd/daemon", + "//base/update/updater/services/flashd/host", + "//base/update/updater/services/flashd/common", "//base/update/updater/services/fs_manager", "//base/update/updater/services/applypatch", "//base/update/updater/services/diffpatch", @@ -164,6 +176,9 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/diffpatch/bzip2", "//base/update/updater/services/ui", "//base/update/updater/test/unittest", + "//developtools/hdc_standard/src/common", + "//developtools/hdc_standard/src/host", + "//developtools/hdc_standard/src/daemon", "//third_party/zlib", "//third_party/lz4/lib", "//third_party/bounds_checking_function/include", @@ -185,6 +200,7 @@ ohos_unittest("updater_unittest") { "//drivers/peripheral/input/hal/include", "//drivers/peripheral/input/interfaces/include", "//third_party/bounds_checking_function/include", + "//base/startup/init_lite/interfaces/innerkits/include", ] deps = [ "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static", @@ -193,6 +209,7 @@ ohos_unittest("updater_unittest") { "//base/update/updater/services/applypatch:libapplypatch", "//base/update/updater/services/diffpatch/diff:libdiff", "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/flashd:flashd_deamon", "//base/update/updater/services/fs_manager:libfsmanager", "//base/update/updater/services/log:libupdaterlog", "//base/update/updater/services/package:libupdaterpackage", @@ -203,6 +220,7 @@ ohos_unittest("updater_unittest") { "//third_party/cJSON:cjson_static", "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", + "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", @@ -219,6 +237,9 @@ ohos_unittest("updater_unittest") { defines = [ "UPDATER_UT", "BUILD_OHOS", + "HDC_DEBUG", + "HDC_SUPPORT_FLASHD", + "HARMONY_PROJECT", ] public_configs = [ ":utest_config" ] diff --git a/test/unittest/applypatch_test/imagepatch_unittest.h b/test/unittest/applypatch_test/imagepatch_unittest.h index e4cdc358c06550761f859a1bf570cd8f4aee55f2..6da5f553f987e8d7f6cc47979d316a75a9f0c473 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.h +++ b/test/unittest/applypatch_test/imagepatch_unittest.h @@ -77,7 +77,9 @@ public: int fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, mode); EXPECT_GE(fd, 0); BlockSet targetBlk; - targetBlk.ParserAndInsert({"2", "0", "1"}); + targetBlk.ParserAndInsert({ + "2", "0", "1" + }); std::unique_ptr writer = std::make_unique(fd, targetBlk); std::vector empty; int32_t ret = updatepatch::UpdatePatch::ApplyImagePatch(param, empty, diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp index c4e6d023bd46a8d20500b41fc03a0a7e047bcb28..d7c4e068d4580fce594487655e1ab94c7691d67e 100755 --- a/test/unittest/flashd_test/flash_host_unittest.cpp +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -18,10 +18,11 @@ #include #include -#include "common/common.h" -#include "common/transfer.h" +#include "common.h" +#include "flash_define.h" #include "host_updater.h" #include "serial_struct.h" +#include "transfer.h" #include "unittest_comm.h" using namespace std; @@ -29,8 +30,8 @@ using namespace Hdc; using namespace testing::ext; namespace { static std::string TEST_PARTITION_NAME = "data"; -static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/src/updater.zip"; -static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/src/image/userdata.img"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/updater/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/updater/test.img"; class FLashHostUnitTest : public testing::Test { public: @@ -46,59 +47,201 @@ public: public: int TestFlashHost(uint16_t command, const std::string &cmd) { - uv_loop_t loopMain; - uv_loop_init(&loopMain); - HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; - hTaskInfo->runLoop = &loopMain; + hTaskInfo->runLoop = uv_default_loop(); hTaskInfo->serverOrDaemon = 0; + hTaskInfo->ownerSessionClass = nullptr; std::shared_ptr flashHost = std::make_shared(hTaskInfo); + if (flashHost == nullptr) { + return -1; + } flashHost->CommandDispatch(command, const_cast(reinterpret_cast(cmd.data())), cmd.size()); return 0; } -}; -HWTEST_F(FLashHostUnitTest, TestFlashHost, TestSize.Level1) -{ - FLashHostUnitTest test; + int TestFlashProgress(uint16_t command, const std::string &cmd, uint32_t progress) + { + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } + hTaskInfo = task.get(); + hTaskInfo->channelId = 1; + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = uv_default_loop(); + hTaskInfo->serverOrDaemon = 0; + hTaskInfo->ownerSessionClass = nullptr; + std::shared_ptr flashHost = std::make_shared(hTaskInfo); + if (flashHost == nullptr) { + return -1; + } + flashHost->CommandDispatch(command, + const_cast(reinterpret_cast(cmd.data())), cmd.size()); + flashHost->OpenFile(); - std::string cmdParam = "update "; - cmdParam += TEST_UPDATER_PACKAGE_PATH; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_UPDATE_INIT, cmdParam)); + std::vector data(MAX_SIZE_IOBUF * 2); // 2 + flashHost->CommandDispatch(CMD_UPDATER_BEGIN, const_cast(data.data()), data.size()); - cmdParam = "flash "; - cmdParam += TEST_PARTITION_NAME + " "; - cmdParam += TEST_FLASH_IMAGE_NAME; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FLASH_INIT, cmdParam)); + std::string cmdInfo = ""; + flashHost->CommandDispatch(CMD_UPDATER_CHECK, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_CHECK, cmdParam)); + flashHost->CommandDispatch(CMD_UPDATER_DATA, const_cast(data.data()), data.size()); - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_BEGIN, cmdParam)); + vector info = {0, 1, 's', 'u', 'c', 'c', 'e', 's', 's'}; + flashHost->CommandDispatch(CMD_UPDATER_FINISH, + const_cast(reinterpret_cast(info.data())), info.size()); - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_DATA, cmdParam)); + uint32_t percentage = 30; // 30 progress + cmdInfo.resize(sizeof(percentage)); + (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); + flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + + percentage = static_cast(progress); + cmdInfo.resize(sizeof(percentage)); + (void)memcpy_s(cmdInfo.data(), cmdInfo.size(), &percentage, sizeof(percentage)); + flashHost->CommandDispatch(CMD_UPDATER_PROGRESS, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + return 0; + } +}; - cmdParam = ""; - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FINISH, cmdParam)); +HWTEST_F(FLashHostUnitTest, TestFlashHostErase, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print - cmdParam = "erase -f "; + std::string cmdParam = "erase -f "; cmdParam += TEST_PARTITION_NAME; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); +} - cmdParam = "format -f "; +HWTEST_F(FLashHostUnitTest, TestFlashHostFormat, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = "format -f "; + cmdParam += TEST_PARTITION_NAME; + cmdParam += " -t ext4"; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); + + cmdParam = "format "; cmdParam += TEST_PARTITION_NAME; + cmdParam += " -t ext4"; EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_FORMAT, cmdParam)); +} + +HWTEST_F(FLashHostUnitTest, TestFlashHostUpdater, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_UPDATE_INIT, cmdParam, -1)); + + cmdParam = " -f "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, -1)); +} + +HWTEST_F(FLashHostUnitTest, TestFlashHostFlash, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = TEST_UPDATER_PACKAGE_PATH; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_UPDATE_INIT, cmdParam, 100)); + cmdParam = " -f "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashProgress(CMD_UPDATER_FLASH_INIT, cmdParam, 100)); +} + +HWTEST_F(FLashHostUnitTest, TestFlashHostMatch, TestSize.Level1) +{ + std::string stringError; + uint16_t cmdFlag = 0; + bool bJumpDo = false; + bool ret = HostUpdater::CheckMatchUpdate("update updater.zip", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_UPDATE_INIT); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("flash updater.zip", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_FLASH_INIT); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("erase -f updater", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_ERASE); + EXPECT_EQ(bJumpDo == false, 1); + + ret = HostUpdater::CheckMatchUpdate("format -f updater ", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(cmdFlag, CMD_UPDATER_FORMAT); + EXPECT_EQ(bJumpDo == false, 1); + + bJumpDo = false; + ret = HostUpdater::CheckMatchUpdate("install aaa.hap", stringError, cmdFlag, bJumpDo); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(bJumpDo == false, 1); +} - uint32_t percentage = 30; // 30 progress - cmdParam.resize(sizeof(percentage)); - memcpy_s(cmdParam.data(), cmdParam.size(), &percentage, sizeof(percentage)); - EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_PROGRESS, cmdParam)); +HWTEST_F(FLashHostUnitTest, TestFlashHostConfirm, TestSize.Level1) +{ + bool closeInput = false; + bool ret = HostUpdater::ConfirmCommand("update updater.zip", closeInput); + EXPECT_EQ(ret == true, 1); + + HostUpdater::SetInput("yes"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("flash updater.zip", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == true, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("erase updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("format -f updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + closeInput = false; + ret = HostUpdater::ConfirmCommand("erase -f updater", closeInput); + EXPECT_EQ(ret == true, 1); + EXPECT_EQ(closeInput == false, 1); + + HostUpdater::SetInput("no"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(closeInput == false, 1); + + HostUpdater::SetInput("eeeeeeeee"); + closeInput = false; + ret = HostUpdater::ConfirmCommand("format updater", closeInput); + EXPECT_EQ(ret == false, 1); + EXPECT_EQ(closeInput == false, 1); } } // namespace \ No newline at end of file diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp index 64b37920325ef337b9a1394248bb6524d9593b03..32b63600814f8b171232436b5346562a652374e3 100755 --- a/test/unittest/flashd_test/flash_service_unittest.cpp +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -18,22 +18,25 @@ #include #include -#include "common/common.h" -#include "common/transfer.h" +#include "common.h" #include "daemon_updater.h" +#include "flash_define.h" #include "flash_service.h" #include "flashd/flashd.h" +#include "fs_manager/mount.h" #include "serial_struct.h" +#include "transfer.h" #include "unittest_comm.h" using namespace std; using namespace flashd; using namespace Hdc; using namespace testing::ext; + namespace { static std::string TEST_PARTITION_NAME = "data"; -static std::string TEST_UPDATER_PACKAGE_PATH = "/home/axw/develop/updater.zip"; -static std::string TEST_FLASH_IMAGE_NAME = "/home/axw/develop/image/userdata.img"; +static std::string TEST_UPDATER_PACKAGE_PATH = "/data/updater/updater/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/updater/updater.zip"; class FLashServiceUnitTest : public testing::Test { public: @@ -49,6 +52,7 @@ public: public: int TestFindAllDevice() { + updater::LoadFstab(); std::string errorMsg; std::shared_ptr flash = std::make_shared(errorMsg); if (flash == nullptr) { @@ -69,6 +73,18 @@ public: return 0; } + int TestDoUpdater() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoUpdate(TEST_UPDATER_PACKAGE_PATH); + flash->PostProgress(UPDATEMOD_UPDATE, 1024 * 1024 * 4, nullptr); // 1024 * 1024 * 4 4M + return 0; + } + int TestDoErasePartition() { std::string errorMsg; @@ -80,14 +96,26 @@ public: return 0; } - int TestDoFormatPartition() + int TestDoFormatPartition(const std::string &part, const std::string &type) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoFormatPartition(part, type); + return 0; + } + + int TestFlashServiceDoResizeParatiton() { std::string errorMsg; std::shared_ptr flash = std::make_shared(errorMsg); if (flash == nullptr) { return 1; } - flash->DoFormatPartition(TEST_PARTITION_NAME, "ext4"); + flash->DoResizeParatiton("data", 4096); // 4096 partition size + flash->DoResizeParatiton("data", 1024); // 1024 partition size return 0; } @@ -131,12 +159,18 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 1; hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc updater packagename // check @@ -148,7 +182,6 @@ public: WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); transferConfig.optionalName = "updater.zip"; std::string bufString = SerialStruct::SerializeToString(transferConfig); - // 当前升级包中总的文件的大小 const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; std::vector buffer(sizeof(realSize) + bufString.size()); int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); @@ -160,41 +193,80 @@ public: // begin hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); - // data 写数据部分 - const uint32_t dataSize = 1024; // 1024 data size - HdcTransferBase::TransferPayload payloadHead {}; - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 0; - std::string bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); - - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 1; - bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + for (int i = 0; i < 10; i++) { // 10 send time + HdcTransferBase::TransferPayload payloadHead {}; + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + } // end hdcDamon->DoTransferFinish(); return 0; } - int TestHdcDaemonFlash() + int TestHdcDaemonInvalid() { uv_loop_t loopMain; uv_loop_init(&loopMain); HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } + // cmd: hdc flash partition packagename + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "aaaa"; + transferConfig.options = TEST_PARTITION_NAME; + transferConfig.options += " "; + transferConfig.options += TEST_FLASH_IMAGE_NAME; + std::string localPath = TEST_FLASH_IMAGE_NAME; + transferConfig.fileSize = 1468006400; // 1468006400 file size + WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); + transferConfig.optionalName = "userdata.img"; + std::string bufString = SerialStruct::SerializeToString(transferConfig); + const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + EXPECT_EQ(0, ret); + ret = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + EXPECT_EQ(0, ret); + hdcDamon->CommandDispatch(CMD_UPDATER_CHECK, buffer.data(), buffer.size()); + return 0; + } + + int TestHdcDaemonFlash() + { + uv_loop_t loopMain; + uv_loop_init(&loopMain); + HTaskInfo hTaskInfo = nullptr; + std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } + hTaskInfo = task.get(); + hTaskInfo->channelId = 2; // 2 channel id + hTaskInfo->sessionId = 0; + hTaskInfo->runLoop = &loopMain; + hTaskInfo->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc flash partition packagename // check HdcTransferBase::TransferConfig transferConfig {}; @@ -207,8 +279,7 @@ public: WRITE_LOG(LOG_DEBUG, "CheckMaster %s", transferConfig.functionName.c_str()); transferConfig.optionalName = "userdata.img"; std::string bufString = SerialStruct::SerializeToString(transferConfig); - // 当前升级包中总的文件的大小 - const uint64_t realSize = static_cast(1024 * 1024 * 1024) * 5; + const uint64_t realSize = transferConfig.fileSize; std::vector buffer(sizeof(realSize) + bufString.size()); int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); EXPECT_EQ(0, ret); @@ -219,22 +290,17 @@ public: // begin hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); - // data 写数据部分 - const uint32_t dataSize = 1024; // 1024 data size HdcTransferBase::TransferPayload payloadHead {}; - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 0; + for (int i = 0; i < 10; i++) { // 10 send data + payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; + payloadHead.uncompressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.compressSize = transferConfig.fileSize / 10; // 10 time + payloadHead.index = 0; + std::string bufData = SerialStruct::SerializeToString(payloadHead); + hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); + } std::string bufData = SerialStruct::SerializeToString(payloadHead); hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); - - payloadHead.compressType = HdcTransferBase::COMPRESS_NONE; - payloadHead.uncompressSize = dataSize; - payloadHead.compressSize = dataSize; - payloadHead.index = 1; - bufData = SerialStruct::SerializeToString(payloadHead); - hdcDamon->CommandDispatch(CMD_UPDATER_DATA, reinterpret_cast(bufData.data()), bufData.size()); // end hdcDamon->DoTransferFinish(); return 0; @@ -247,20 +313,22 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); - + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc erase partition // check - HdcTransferBase::TransferConfig transferConfig {}; - transferConfig.functionName = "erase"; - transferConfig.options = "erase -f "; - transferConfig.options += TEST_PARTITION_NAME; - std::string bufString = SerialStruct::SerializeToString(transferConfig); + std::string bufString = "erase -f "; + bufString += TEST_PARTITION_NAME; hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); return 0; } @@ -272,21 +340,24 @@ public: HTaskInfo hTaskInfo = nullptr; std::shared_ptr task = std::make_shared(); + if (task == nullptr) { + return -1; + } hTaskInfo = task.get(); hTaskInfo->channelId = 2; // 2 channel id hTaskInfo->sessionId = 0; hTaskInfo->runLoop = &loopMain; hTaskInfo->serverOrDaemon = 1; std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); - + if (hdcDamon == nullptr) { + return -1; + } // cmd: hdc format partition // check - HdcTransferBase::TransferConfig transferConfig {}; - transferConfig.functionName = "format"; - transferConfig.options = "format -f "; - transferConfig.options += TEST_PARTITION_NAME; - std::string bufString = SerialStruct::SerializeToString(transferConfig); - hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); + std::string bufString = "format -f "; + bufString += TEST_PARTITION_NAME + " -t ext4"; + hdcDamon->CommandDispatch(CMD_UPDATER_FORMAT, reinterpret_cast(bufString.data()), bufString.size()); + return 0; } }; @@ -303,12 +374,24 @@ HWTEST_F(FLashServiceUnitTest, TestDaemonUpdater, TestSize.Level1) EXPECT_EQ(0, test.TestDaemonUpdater()); } +HWTEST_F(FLashServiceUnitTest, TestDoUpdater, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoUpdater()); +} + HWTEST_F(FLashServiceUnitTest, TestHdcDaemonFlash, TestSize.Level1) { FLashServiceUnitTest test; EXPECT_EQ(0, test.TestHdcDaemonFlash()); } +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonInvalid, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonInvalid()); +} + HWTEST_F(FLashServiceUnitTest, TestHdcDaemonErase, TestSize.Level1) { FLashServiceUnitTest test; @@ -336,7 +419,9 @@ HWTEST_F(FLashServiceUnitTest, TestDoFlashPartition, TestSize.Level1) HWTEST_F(FLashServiceUnitTest, TestDoFormatPartition, TestSize.Level1) { FLashServiceUnitTest test; - EXPECT_EQ(0, test.TestDoFormatPartition()); + EXPECT_EQ(0, test.TestDoFormatPartition("data", "ext4")); + EXPECT_EQ(0, test.TestDoFormatPartition("data", "f2fs")); + EXPECT_EQ(0, test.TestDoFormatPartition("boot", "f2fs")); } HWTEST_F(FLashServiceUnitTest, TestDoErasePartition, TestSize.Level1) @@ -345,6 +430,12 @@ HWTEST_F(FLashServiceUnitTest, TestDoErasePartition, TestSize.Level1) EXPECT_EQ(0, test.TestDoErasePartition()); } +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoResizeParatiton, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFlashServiceDoResizeParatiton()); +} + HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoPrepare, TestSize.Level1) { FLashServiceUnitTest test; @@ -361,7 +452,7 @@ HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoPrepare, TestSize.Level1) EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_ERASE, cmdParam)); cmdParam = "format -f "; - cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_PARTITION_NAME + " -t ext4"; EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FORMAT, cmdParam)); EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_MAX, cmdParam)); @@ -382,11 +473,11 @@ HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFlash, TestSize.Level1) cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_ERASE, cmdParam)); - cmdParam = "format -f ext4 "; + cmdParam = "format -f -t ext4 "; cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); - cmdParam = "format -f f2fs "; + cmdParam = "format -f -t f2fs "; cmdParam += TEST_PARTITION_NAME + " "; EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); diff --git a/test/unittest/package/package_unittest.cpp b/test/unittest/package/package_unittest.cpp index 381c58f6df4d1ac4ddac7c4c304984ae85776858..5031c3e02f240de75df34e57be0eb0cd8b7b4d3a 100755 --- a/test/unittest/package/package_unittest.cpp +++ b/test/unittest/package/package_unittest.cpp @@ -38,7 +38,7 @@ public: PackageUnitTest() {} ~PackageUnitTest() override {} public: - int TestPackagePack() + int TestPackagePack(int type = PKG_DIGEST_TYPE_SHA256) { int32_t ret; uint32_t updateFileVersion = 1000; @@ -48,7 +48,7 @@ public: pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); pkgInfo.entryCount = testFileNames_.size(); - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.digestMethod = type; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; pkgInfo.updateFileVersion = updateFileVersion; @@ -74,7 +74,8 @@ public: } std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), + GetTestPrivateKeyName(pkgInfo.digestMethod).c_str()); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < testFileNames_.size(); i++) { free(comp[i].componentAddr); @@ -88,13 +89,13 @@ public: return ret; } - int TestPackageUnpack() + int TestPackageUnpack(int type) { pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; // 使用上面打包的包进行解析 - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(type), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -104,17 +105,18 @@ public: return PKG_SUCCESS; } - int TestZipPkgCompress() + int TestZipPkgCompress(int digestMethod) { - return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM); + return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM, digestMethod); } - int TestZipPkgDecompress() + int TestZipPkgDecompress(int digestMethod) { pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testZipPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testZipPackageName, + GetTestCertName(digestMethod), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -146,7 +148,8 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_LZ4; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; - return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestLz4PkgCompressBlock() @@ -170,7 +173,8 @@ public: pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.pkgType = PKG_PACK_TYPE_LZ4; - return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestLz4PkgDecompress() @@ -178,7 +182,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testLz4PackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testLz4PackageName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -197,7 +201,7 @@ public: std::vector fileNames; fileNames.push_back(testZipPackageName); fileNames.push_back(testPackageName); - ret = CreateZipPackage(fileNames, TEST_PATH_TO + testCombinePkgName, TEST_PATH_TO); + ret = CreateZipPackage(fileNames, TEST_PATH_TO + testCombinePkgName, TEST_PATH_TO, PKG_DIGEST_TYPE_SHA256); EXPECT_EQ(ret, PKG_SUCCESS); return 0; } @@ -208,7 +212,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(pkgManager_, nullptr); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -228,30 +232,30 @@ public: std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), TEST_PATH_TO + testPackageName); std::string path = TEST_PATH_TO + testPackageName; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(0, ret); constexpr uint32_t digestLen = 10; digest[digestLen] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } int TestVerifyZipWithCallback() { - int32_t ret = TestVerifyZip(); + int32_t ret = TestVerifyZip(PKG_DIGEST_TYPE_SHA256); EXPECT_EQ(ret, 0); std::string path = GetCurrPath(); path = TEST_PATH_TO + testZipPackageName; - ret = VerifyPackageWithCallback(path.c_str(), GetTestCertName().c_str(), + ret = VerifyPackageWithCallback(path.c_str(), GetTestCertName(0).c_str(), [](int32_t result, uint32_t percent) { PKG_LOGI("current progress: %u\n", percent); }); EXPECT_EQ(PKG_INVALID_PARAM, ret); return 0; } - int TestVerifyZip() + int TestVerifyZip(int digestMethod) { - int32_t ret = TestZipPkgCompress(); + int32_t ret = TestZipPkgCompress(digestMethod); EXPECT_EQ(ret, 0); constexpr size_t digestSize = 32; uint8_t digestValue = 33; @@ -260,10 +264,12 @@ public: path = TEST_PATH_TO + testZipPackageName; std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), path); - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(digestMethod).c_str(), + std::to_string(digestMethod).c_str(), digest.data(), digest.capacity()); EXPECT_EQ(ret, 0); digest[index] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), + std::to_string(digestMethod).c_str(), digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } @@ -279,10 +285,10 @@ public: path = TEST_PATH_TO + testLz4PackageName; std::vector digest(digestSize); BuildFileDigest(*digest.data(), digest.capacity(), path); - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(0, ret); digest[index] = digestValue; - ret = VerifyPackage(path.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.capacity()); + ret = VerifyPackage(path.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.capacity()); EXPECT_EQ(PKG_INVALID_SIGNATURE, ret); return 0; } @@ -309,7 +315,8 @@ public: } std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + int32_t ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), + GetTestPrivateKeyName(pkgInfo.digestMethod).c_str()); for (size_t i = 0; i < testFileNames_.size(); i++) { free(comp[i].componentAddr); free(comp[i].filePath); @@ -319,7 +326,7 @@ public: uint8_t digest[digestSize] = {0}; ret = BuildFileDigest(*digest, sizeof(digest), packagePath); EXPECT_EQ(ret, PKG_SUCCESS); - ret = VerifyPackage(packagePath.c_str(), GetTestCertName().c_str(), "", digest, digestSize); + ret = VerifyPackage(packagePath.c_str(), GetTestCertName(0).c_str(), "", digest, digestSize); return ret; } @@ -355,30 +362,30 @@ public: std::vector digest(digestSize); ret = BuildFileDigest(*digest.data(), digest.size(), packagePath.c_str()); EXPECT_EQ(ret, PKG_SUCCESS); - return VerifyPackage(packagePath.c_str(), GetTestCertName().c_str(), "", digest.data(), digest.size()); + return VerifyPackage(packagePath.c_str(), GetTestCertName(0).c_str(), "", digest.data(), digest.size()); } int TestInvalidCreatePackage() const { ComponentInfoExt compInfo; uint8_t pkgType = 5; - int ret = CreatePackage(nullptr, &compInfo, nullptr, GetTestPrivateKeyName().c_str()); + int ret = CreatePackage(nullptr, &compInfo, nullptr, GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); UpgradePkgInfoExt pkgInfoExt; pkgInfoExt.pkgType = pkgType; - ret = CreatePackage(&pkgInfoExt, &compInfo, nullptr, GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfoExt, &compInfo, nullptr, GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); constexpr uint32_t digestLen = 32; - ret = VerifyPackage(nullptr, GetTestCertName().c_str(), nullptr, nullptr, digestLen); + ret = VerifyPackage(nullptr, GetTestCertName(0).c_str(), nullptr, nullptr, digestLen); EXPECT_EQ(ret, PKG_INVALID_PARAM); // 无效的类型 std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; pkgInfoExt.pkgType = pkgType; - ret = CreatePackage(&pkgInfoExt, &compInfo, packagePath.c_str(), GetTestPrivateKeyName().c_str()); + ret = CreatePackage(&pkgInfoExt, &compInfo, packagePath.c_str(), GetTestPrivateKeyName(0).c_str()); EXPECT_EQ(ret, PKG_INVALID_PARAM); return 0; } @@ -403,7 +410,8 @@ public: pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.pkgType = PKG_PACK_TYPE_GZIP; - return pkgManager_->CreatePackage(TEST_PATH_TO + testGZipPackageName, GetTestPrivateKeyName(), &pkgInfo, files); + return pkgManager_->CreatePackage(TEST_PATH_TO + testGZipPackageName, + GetTestPrivateKeyName(pkgInfo.digestMethod), &pkgInfo, files); } int TestGZipPkgDecompress(const std::string& gzipPackageName) @@ -411,7 +419,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(nullptr, pkgManager_); std::vector components; - int32_t ret = pkgManager_->LoadPackage(gzipPackageName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(gzipPackageName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_SUCCESS); for (size_t i = 0; i < components.size(); i++) { @@ -440,7 +448,7 @@ public: pkgManager_ = static_cast(PkgManager::GetPackageInstance()); EXPECT_NE(nullptr, pkgManager_); std::vector fileIds; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(), fileIds); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testPackageName, GetTestCertName(0), fileIds); EXPECT_EQ(0, ret); // 在load其中的一个zip包 PkgManager::StreamPtr outStream = nullptr; @@ -451,7 +459,7 @@ public: EXPECT_EQ(ret, 0); pkgManager_->ClosePkgStream(outStream); std::vector secondFileIds; - ret = pkgManager_->LoadPackage(TEST_PATH_TO + secondFile, GetTestCertName(), secondFileIds); + ret = pkgManager_->LoadPackage(TEST_PATH_TO + secondFile, GetTestCertName(0), secondFileIds); EXPECT_EQ(0, ret); if (secondFileIds.size() != 1) { EXPECT_EQ(1, ret); @@ -563,15 +571,29 @@ public: HWTEST_F(PackageUnitTest, TestPackage, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestPackagePack()); - EXPECT_EQ(0, test.TestPackageUnpack()); + EXPECT_EQ(0, test.TestPackagePack(PKG_DIGEST_TYPE_SHA256)); + EXPECT_EQ(0, test.TestPackageUnpack(PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PackageUnitTest, TestPackage384, TestSize.Level1) +{ + PackageUnitTest test; + EXPECT_EQ(0, test.TestPackagePack(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestPackageUnpack(PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PackageUnitTest, TestZipPackage, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestZipPkgCompress()); - EXPECT_EQ(0, test.TestZipPkgDecompress()); + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA256)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PackageUnitTest, TestZipPackage384, TestSize.Level1) +{ + PackageUnitTest test; + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PackageUnitTest, TestLz4Package, TestSize.Level1) @@ -609,7 +631,8 @@ HWTEST_F(PackageUnitTest, TestVerifyZipWithCallback, TestSize.Level1) HWTEST_F(PackageUnitTest, TestVerifyZip, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVerifyZip()); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA256)); } HWTEST_F(PackageUnitTest, TestVerifyLz4, TestSize.Level1) { diff --git a/test/unittest/package/pkg_algo_unittest.cpp b/test/unittest/package/pkg_algo_unittest.cpp index fbab4b1c78aac23baa98a1b4dd6383b5c8615257..43836721c6108b3ebcb56a5b0859abd077f2990c 100755 --- a/test/unittest/package/pkg_algo_unittest.cpp +++ b/test/unittest/package/pkg_algo_unittest.cpp @@ -131,7 +131,7 @@ public: return 0; } - int TestSignVerify(int8_t signMethod, std::string privateKey, std::string certName) + int TestSignVerify(int8_t signMethod, std::string privateKey, std::string certName, uint8_t hashType) { PkgBuffer digest(DIGEST_LEN); std::string filePath = TEST_PATH_FROM; @@ -141,7 +141,7 @@ public: // 签名 filePath = TEST_PATH_FROM + privateKey; SignAlgorithm::SignAlgorithmPtr algorithm = PkgAlgorithmFactory::GetSignAlgorithm(filePath, - signMethod, PKG_DIGEST_TYPE_SHA256); + signMethod, hashType); EXPECT_NE(nullptr, algorithm); std::vector signature; size_t signLen = 0; @@ -152,7 +152,7 @@ public: EXPECT_EQ(ret, PKG_INVALID_SIGNATURE); filePath = TEST_PATH_FROM + certName; - algorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(filePath, PKG_DIGEST_TYPE_SHA256); + algorithm = PkgAlgorithmFactory::GetVerifyAlgorithm(filePath, hashType); // 验证 ret = algorithm->SignBuffer(digest, signature, signLen); EXPECT_EQ(ret, PKG_INVALID_SIGNATURE); @@ -229,13 +229,22 @@ HWTEST_F(PkgAlgoUnitTest, TestHash256Digest, TestSize.Level1) HWTEST_F(PkgAlgoUnitTest, TestRsaSignVerify, TestSize.Level1) { PkgAlgoUnitTest test; - EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, "rsa_private_key2048.pem", "signing_cert.crt")); + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, + "rsa_private_key2048.pem", "signing_cert.crt", PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PkgAlgoUnitTest, TestRsaSignVerify384, TestSize.Level1) +{ + PkgAlgoUnitTest test; + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_RSA, + "rsa_private_key384.pem", "signing_cert384.crt", PKG_DIGEST_TYPE_SHA384)); } HWTEST_F(PkgAlgoUnitTest, TestEccSignVerify, TestSize.Level1) { PkgAlgoUnitTest test; - EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_ECDSA, "ecc/prime256v1-key.pem", "ecc/signing_cert.crt")); + EXPECT_EQ(0, test.TestSignVerify(PKG_SIGN_METHOD_ECDSA, + "ecc/prime256v1-key.pem", "ecc/signing_cert.crt", PKG_DIGEST_TYPE_SHA256)); } HWTEST_F(PkgAlgoUnitTest, TestEccUserPackage, TestSize.Level1) diff --git a/test/unittest/package/pkg_manager_unittest.cpp b/test/unittest/package/pkg_manager_unittest.cpp index b7143e9fabdc59964d203a2db244bb45b2cb41df..dcbf120d6ee11d29fef978d8c1567cc33f874f88 100755 --- a/test/unittest/package/pkg_manager_unittest.cpp +++ b/test/unittest/package/pkg_manager_unittest.cpp @@ -137,7 +137,7 @@ public: GetUpgradePkgInfo(pkgInfo, files); std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_SUCCESS); return 0; } @@ -153,7 +153,7 @@ public: // 修改成错误的路径 files[0].first = "sssssssssss"; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -164,7 +164,7 @@ public: std::vector> files; std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), nullptr, files); + int32_t ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), nullptr, files); EXPECT_EQ(ret, PKG_INVALID_PARAM); return 0; } @@ -177,7 +177,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGE("LoadPackage fail ret:%d", ret); return ret; @@ -258,7 +258,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGI("LoadPackage fail ret:%d", ret); return ret; @@ -297,7 +297,7 @@ public: } PKG_LOGI("\n\n ************* TestCombinePkgUNpack %s \r\n", testCombinePkgName.c_str()); std::vector components; - int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testCombinePkgName, GetTestCertName(0), components); if (ret != PKG_SUCCESS) { PKG_LOGI("LoadPackage fail ret:%d", ret); return ret; @@ -404,7 +404,7 @@ public: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; files.push_back(std::pair("/qqqqqq", info)); - int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -418,7 +418,7 @@ public: packagePath += testPackageName; uint8_t signMethodIndex = 10; pkgInfo.pkgInfo.signMethod = PKG_SIGN_METHOD_RSA + signMethodIndex; - int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(), &pkgInfo.pkgInfo, files); + int ret = pkgManager_->CreatePackage(packagePath, GetTestPrivateKeyName(0), &pkgInfo.pkgInfo, files); EXPECT_NE(ret, 0); return 0; } @@ -440,7 +440,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_GZIP; std::string fileName = TEST_PATH_TO; fileName += testGZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -463,7 +463,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_GZIP + pkgTypeIndex; std::string fileName = TEST_PATH_TO; fileName += testGZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -487,7 +487,7 @@ public: pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; std::string fileName = TEST_PATH_TO; fileName += testZipPackageName; - int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(), &pkgInfo, files); + int ret = pkgManager_->CreatePackage(fileName, GetTestPrivateKeyName(0), &pkgInfo, files); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } @@ -499,7 +499,7 @@ public: std::vector components; std::string fileName = TEST_PATH_TO; fileName += "testZipPackageName.aaa"; - int32_t ret = pkgManager_->LoadPackage(fileName, GetTestCertName(), components); + int32_t ret = pkgManager_->LoadPackage(fileName, GetTestCertName(0), components); EXPECT_EQ(ret, PKG_INVALID_FILE); return 0; } diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index bdd92603bbf11c3e988fefb1ca4b1e22b8483080..2880e5cd04daff5a378b9a3cccc840e321d55909 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -38,8 +38,6 @@ namespace { constexpr uint32_t MAX_FILE_NAME = 256; constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; -constexpr uint32_t ZIP_NODE_ID = 100; -constexpr size_t GIANT_NUMBER = 100000; class TestFile : public PkgFile { public: @@ -122,13 +120,14 @@ public: EXPECT_NE(pkgManager_, nullptr); PkgManager::StreamPtr stream = nullptr; std::string packagePath = TEST_PATH_TO; + uint32_t zipNodeId = 100; packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); std::unique_ptr file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); - std::unique_ptr entry = std::make_unique(file.get(), ZIP_NODE_ID); + std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); EXPECT_NE(entry, nullptr); string name = "TestBigZip"; @@ -162,7 +161,8 @@ public: EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); - size_t size = UINT_MAX + GIANT_NUMBER; + size_t giantNumber = 100000; + size_t size = UINT_MAX + giantNumber; WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetWord, size); WriteLE64(buff.data() + sizeof(CentralDirEntry) + name.length() + offset3Words, size); size_t decodeLen = 0; diff --git a/test/unittest/package/pkg_test.h b/test/unittest/package/pkg_test.h index 16a72a4df063db9699ac7f58dc2f34d6fb429636..e650d2985ab1caa550d828e45915bf15bce5b74a 100755 --- a/test/unittest/package/pkg_test.h +++ b/test/unittest/package/pkg_test.h @@ -142,7 +142,7 @@ protected: } int CreateZipPackage(const std::vector &testFileNames, - const std::string packageName, const std::string &base) + const std::string packageName, const std::string &base, int digestMethod) { PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); EXPECT_NE(pkgManager, nullptr); @@ -159,9 +159,9 @@ protected: PkgInfo pkgInfo; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.digestMethod = digestMethod; pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; - int32_t ret = pkgManager->CreatePackage(packageName, GetTestPrivateKeyName(), &pkgInfo, files); + int32_t ret = pkgManager->CreatePackage(packageName, GetTestPrivateKeyName(digestMethod), &pkgInfo, files); EXPECT_EQ(ret, 0); return ret; } diff --git a/test/unittest/test_data/src/rsa_private_key384.pem b/test/unittest/test_data/src/rsa_private_key384.pem new file mode 100755 index 0000000000000000000000000000000000000000..9ade6de3b3a2414d6fc80204d70ce075ac0377f8 --- /dev/null +++ b/test/unittest/test_data/src/rsa_private_key384.pem @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG5QIBAAKCAYEA0mDyEBQc9A/z+la197GMMhFAkL/g1TNnGo5cIm+dclLom4sY +3MDTtxf/GfuNeVdGOIimUb2Zu1XqZaV+HSRh7bggqfwZ9RMgJkHlMpm8JFG9y0Nj +lon+HQdme4jU+p1r4ZycWw2P16PwTBv2pGhd0/yIas909H97nIldyPsfDiO4gxoQ +uVMpeVEK+32j0bFpelZzgn3sQdyXKRNFS8wCt64p3TMFVO1HZaGt+e7UQV6dqQgj +QOUwiEKMdgGI+Day9OGYu0Y5S13adltQKGbwE8J+KNNtTuzWaVZXJzGcNykDSZVi +r/pbVqhbMEPnpsMJ4zMwZY/bL3TYqwG2BbmRb+NJej0Uh7LurHNScxSP0/qEzbkm +tnVtTvIrvVlbLc6r2TebU4fDhFIi3obRGCBBar6epZM7Rz7e0v45MYlWEEyJcUqO +s0zlqccveBO+J4He3bUiHI0fdG2oAfYetgT3Mo/EwH6QEVDcUYazuJTnihDT478k +obZqTwwxRrIOECBrAgMBAAECggGBALR65M80Yg5jLTyDbQJ8t7gwIsLLSbe9rGMU +5CfKtzjftZvS/dZMOpTlqj0BGEKTw7M2T/DqBlu3fioLiqC3mKeWgbcyhpY//SG1 +AEqjpstFsNwTCPmZkn4W3i12mrgRmv5nG5/lh5RImRrCFpq+ylfVWra/GSezwjjt +g56rCN5ZeK5ICzbiCD+CbjiIdaSsXb/NMLUvECMEek2LsbQv5djsOhAA+D7+fHTM ++nLjGAaog/sB9zRyKmuLI/MMqBPA38GT80ufzA9wqjr08luTt+LBhEOWJgCwvn1U +O56SMXcCvBW2eVlXzh4nDTwipihj9+nBn9UXMn/l39tKLupIz1oQEbA7+/1CI3wA +gXK8BkBRbYuulGNZTBBZB9gq8HYy9zUl/RwNqE2p3E0nHhKlQtTPdUVq+z822Q/E +TJMOHzQzBJqj6oii5rRPGmjICXFFfgOVydBo0dYq+/2mMxDjGzpeDOaHQgq06tsj +IesCTyfqTKRrWuYW8IRl34mxoX6OYQKBwQDoKeOjRDkBBrkTRwfMHIYSuBlgAunr +0JG6rtZ3wYSKCweS/OQbviV7EpoVLCAmqjgPLbIIBmxK2+xfH8a/83SesW/Jwd2C +1umJPVu+N8Kwpc+XNeN3Pjwp3DSCsXBNb1rsOBw/vsolKWM5KxqG7qUa/CVtbJO+ +/5r87Rbw6A+cldNR383QeBKsPhdZYD5eh8g5btavV3knfG50TwfL0uNxKfu0l9Oq +jR9C+BC4DsZMBLBlUz/VrAtux8y5nsytibsCgcEA5/p36b7zYqD+2PHviqEVf007 +P7CqL8AZge7fDHi/hgMzSMIt+jgfvO+beNPcadqAeJ26/BZJZpL1lsU7+tUZYB3B +/h3TZp4/JVnT9Y24QB9y1aCLa+vZ60ItaGwOlltGhojIG3/YtslgG80e/4Ob1nMM +y/tSfUlzD2jVUqmUSNtpcTScAs14FAsYv7HRZskNfT11nKuVW5h5zVDmxb27FkK7 +m2lRPWAVHgwrvdAD9F0oUAAoH+Y5SXujYkz/3MERAoHBANIXJiJW2GbvWIfzXUD+ +Bu3ln0DdIiX9pgKTuQzCGFh7Rq1jIGFinrRSzxCdz7JtkzFZHqRYe6L6hVpHfSmy +/DOnSgv/3Z5LMSa6Wc021H3abpLddywvK26OEQ67126beGIPHLEqy+75Fwti0CyO +xOY4iv4MpV7QG8cKHhp/RbFje8m5h5xBLFSmE6cTix0sLqqafLhLph1vYtzpr5pp +Ct0bKuXwBuFtt3540VheNmAQVjg7L6cCe44STFclNv9LhQKBwQDiwsz6+gSyMcxM +x1qv+byo3xb+sDP8T1zfzV/Nsi8N0g0Mn3wQL1Ke/t3MY9T+yG9y+ERy7Vo84YUe +J5j1HeAbO5uJSyB+HEx/t2phi3JDhDpdpv0Ctt8jgGIgxBgSVBEBq61obDWsn/bJ +1l3pyX3JSFeHAhpljCnkM0br8gaYnZpZ5eJnPvCVLy+3GxwlzHzaIvzX9EYg7lCK +Kf4b59Z88Siwx2d5hnW+FImhlzh2Y6XnZe/TFtqDAU/55GjsIvECgcAXmPO1hSlz +nE1Pw5X7AJiF/PjeEYs210Ac1df01mcOa+tDBx+9+m05RjlpZ6bI8AO9606suViB +yPf9DYet+d4cI1FYqQl4B3qXdZl1upYqv4dsLxOztzMIYi7reg0YXVpj2Rhwybzd +onKc9j8KNb55TB1JKHqwvJBhgRpTB6ucxzJYLXal60O6R8Png56S51O3rz3qWh9J +Z48aTa06SIHhDyzDslYddTQ2QpRqWbkRcgOkUY+ZfCpDXjp4YU03Yzk= +-----END RSA PRIVATE KEY----- diff --git a/test/unittest/test_data/src/signing_cert384.crt b/test/unittest/test_data/src/signing_cert384.crt new file mode 100755 index 0000000000000000000000000000000000000000..73e145b0c36c89a323d9b5980caa9768735080e5 --- /dev/null +++ b/test/unittest/test_data/src/signing_cert384.crt @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEazCCAtOgAwIBAgIUWG5lzXTJz5lQ1X2BClMyzltqBhEwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTEwMjgxMTI2MjVaFw0yMjEw +MjgxMTI2MjVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggGiMA0GCSqGSIb3DQEB +AQUAA4IBjwAwggGKAoIBgQDSYPIQFBz0D/P6VrX3sYwyEUCQv+DVM2cajlwib51y +UuibixjcwNO3F/8Z+415V0Y4iKZRvZm7VeplpX4dJGHtuCCp/Bn1EyAmQeUymbwk +Ub3LQ2OWif4dB2Z7iNT6nWvhnJxbDY/Xo/BMG/akaF3T/Ihqz3T0f3uciV3I+x8O +I7iDGhC5Uyl5UQr7faPRsWl6VnOCfexB3JcpE0VLzAK3rindMwVU7Udloa357tRB +Xp2pCCNA5TCIQox2AYj4NrL04Zi7RjlLXdp2W1AoZvATwn4o021O7NZpVlcnMZw3 +KQNJlWKv+ltWqFswQ+emwwnjMzBlj9svdNirAbYFuZFv40l6PRSHsu6sc1JzFI/T ++oTNuSa2dW1O8iu9WVstzqvZN5tTh8OEUiLehtEYIEFqvp6lkztHPt7S/jkxiVYQ +TIlxSo6zTOWpxy94E74ngd7dtSIcjR90bagB9h62BPcyj8TAfpARUNxRhrO4lOeK +ENPjvyShtmpPDDFGsg4QIGsCAwEAAaNTMFEwHQYDVR0OBBYEFMsre/vRH2jpNO5p +K2bpd6a2vxZMMB8GA1UdIwQYMBaAFMsre/vRH2jpNO5pK2bpd6a2vxZMMA8GA1Ud +EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggGBAKSsEIKEy+EDSUT6yoyR8PxK +omQh7BjoLnpBfDXOJZedBKvIyzFh3I5v93xvLknfPWqKrEwnjQorqfDKa6rIaj/o +UjhPFbzBdrB/EF/IYX1+g1t+fxFQLnu0twRr4F3PK/owno3bwE4A09ZBLub0lNws +NYacSTbrmMNaYMZfqhKWzNMkh+9ICx0bxmtRpBJlVyj6agQ9QQQoTz66qsTexe5e +0H4mSkJ0fIQG53jeHPMeOVb2A9Z558OtzlSiXz7H3LX1ca2i6Hn9rjH1axM6wChj +qeaYI9tVXDpXqT/O6tsMFzJ9Lksq3deguaIHx93kCSFsKVvEpYa3SeHcXnA48AaD +NwxS1fKhD/KEhFtBQ8sq6sPzY51hUJirF+pfRk9VBvQ+E6cGVDOgoDn79tPWjFN9 +KI9388+kVxYzQ4OuoxZC7HvrJUsHYZXDgtN7cp5vKcM9Y0rzkUAQh2BddBClAMHP +2LK6qOq0eMjnkeSl7L6f96B7/8ZW3mBT4CDaqcdYvA== +-----END CERTIFICATE----- diff --git a/test/unittest/test_data/updater/test.img b/test/unittest/test_data/updater/test.img new file mode 100755 index 0000000000000000000000000000000000000000..ab7bd1d2d7e84e832b328c39173fd49e321a6188 --- /dev/null +++ b/test/unittest/test_data/updater/test.img @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + test flashd \ No newline at end of file diff --git a/test/unittest/test_data/updater/updater.zip b/test/unittest/test_data/updater/updater.zip index 0ecd1ceb3d60b41a44860a9fc710666b17932235..25795ea99a51b87939255f39b29294349df2d08a 100755 --- a/test/unittest/test_data/updater/updater.zip +++ b/test/unittest/test_data/updater/updater.zip @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14357f75170e22c61470c2cd0fe73ee4f4b1a3396ac5d386433e76c0e54d0cd9 -size 13387850 +oid sha256:d42c282d8f74c3bde0243a39b94150b30f7273bed463a3eaae6a26454bb9eaec +size 1785455 diff --git a/test/unittest/unittest_comm.h b/test/unittest/unittest_comm.h index 2c396bd097cb0a723e1a98c6fcd204bf305180dc..5f75ad3b396856fe36d1baef9be0e5fa65bc3885 100755 --- a/test/unittest/unittest_comm.h +++ b/test/unittest/unittest_comm.h @@ -23,21 +23,30 @@ #include #include +#include "package/package.h" + const std::string TEST_PATH_FROM = "/data/updater/src/"; const std::string TEST_PATH_TO = "/data/updater/dst/"; -inline std::string GetTestPrivateKeyName() +inline std::string GetTestPrivateKeyName(int type = 0) { std::string name = TEST_PATH_FROM; - name += "rsa_private_key2048.pem"; + if (type != PKG_DIGEST_TYPE_SHA384) { + name += "rsa_private_key2048.pem"; + } else { + name += "rsa_private_key384.pem"; + } return name; } -inline std::string GetTestCertName() +inline std::string GetTestCertName(int type = 0) { std::string name = TEST_PATH_FROM; - name += "signing_cert.crt"; + if (type != PKG_DIGEST_TYPE_SHA384) { + name += "signing_cert.crt"; + } else { + name += "signing_cert384.crt"; + } return name; } - #endif // UNITTEST_COMM diff --git a/test/unittest/updater_binary/updater_binary_unittest.cpp b/test/unittest/updater_binary/updater_binary_unittest.cpp index 65975e543ac0b92803baa183def189a9247cf344..d6a48a4d46b264f8bd0cd1f311c114c953d8556d 100755 --- a/test/unittest/updater_binary/updater_binary_unittest.cpp +++ b/test/unittest/updater_binary/updater_binary_unittest.cpp @@ -112,25 +112,26 @@ protected: { int32_t ret; int32_t updateFileVersion = 1000; - int fileNameIndex = 3; - uint8_t componentType = 22; + PKG_LOGI("\n\n ************* CreatePackageBin %s \r\n", testPackageName.c_str()); UpgradePkgInfoExt pkgInfo; - ComponentInfoExt *comp = (ComponentInfoExt*)malloc( - sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); - if (comp == nullptr) { - return -1; - } // C API, Cannot use c++ string class. pkgInfo.softwareVersion = strdup("100.100.100.100"); pkgInfo.date = strdup("2021-02-02"); pkgInfo.time = strdup("21:23:49"); pkgInfo.productUpdateId = strdup("555.555.100.555"); + int fileNameIndex = 3; + uint8_t componentType = 22; pkgInfo.entryCount = testFileNames_.size() + fileNameIndex; pkgInfo.updateFileVersion = updateFileVersion; pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; + ComponentInfoExt *comp = (ComponentInfoExt*)malloc( + sizeof(ComponentInfoExt) * (testFileNames_.size() + fileNameIndex)); + if (comp == nullptr) { + return -1; + } for (size_t i = 0; i < testFileNames_.size(); i++) { BuildCompnentInfo(comp[i], testFileNames_[i], testFileNames_[i], componentType); } @@ -143,9 +144,6 @@ protected: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), GetTestPrivateKeyName().c_str()); - if (ret == 0) { - PKG_LOGI("CreatePackage success offset"); - } for (size_t i = 0; i < index; i++) { free(comp[i].componentAddr); free(comp[i].filePath); diff --git a/test/unittest/updater_main_test/updater_main_unittest.cpp b/test/unittest/updater_main_test/updater_main_unittest.cpp index a3e33c78249f653d7281fcd5eccb2c259481aaad..743278c81c2301b2c07af40679de5510c0cca127 100755 --- a/test/unittest/updater_main_test/updater_main_unittest.cpp +++ b/test/unittest/updater_main_test/updater_main_unittest.cpp @@ -56,7 +56,7 @@ void UpdaterMainUnitTest::SetUpTestCase(void) if (MountForPath("/data") != 0) { cout << "MountForPath failed" << endl; } - PostUpdater(); + PostUpdater(true); } // end @@ -89,7 +89,7 @@ HWTEST_F(UpdaterMainUnitTest, updater_main_test_001, TestSize.Level1) std::vector args = ParseParams(argc, argv); EXPECT_EQ(args.size(), static_cast(argc)); - PostUpdater(); + PostUpdater(true); delete argv[0]; delete []argv; } @@ -106,7 +106,7 @@ HWTEST_F(UpdaterMainUnitTest, updater_main_test_002, TestSize.Level1) int fRet = FactoryReset(USER_WIPE_DATA, "/misc/factory_test"); EXPECT_EQ(fRet, 0); - PostUpdater(); + PostUpdater(true); } HWTEST_F(UpdaterMainUnitTest, updater_main_test_003, TestSize.Level1) diff --git a/utils/updater_reboot.cpp b/utils/updater_reboot.cpp index 7c57ff61a8db71b8af4522ce45f2923cc64101c6..42e189f8a26d7d99922fd562d77919647d2f9c80 100644 --- a/utils/updater_reboot.cpp +++ b/utils/updater_reboot.cpp @@ -32,12 +32,12 @@ int main(int argc, char **argv) std::string updaterStr = "updater"; if (!memcmp(argv[1], updaterStr.c_str(), updaterStr.length())) { updater::utils::DoReboot(argv[1]); - } else if (strcmp(argv[1], "flash") == 0) { + } else if (strcmp(argv[1], "flashd") == 0) { updater::utils::DoReboot(argv[1]); - } else if (strncmp(argv[1], "flash:", strlen("flash:")) == 0) { - updater::utils::DoReboot("flash", argv[1] + strlen("flash:")); + } else if (strncmp(argv[1], "flashd:", strlen("flashd:")) == 0) { + updater::utils::DoReboot("flashd", argv[1] + strlen("flashd:")); } else { - updater::LOG(updater::INFO) << "param must be updater/flash!"; + updater::LOG(updater::INFO) << "param must be updater/flashd!"; } } return 0; diff --git a/utils/utils.cpp b/utils/utils.cpp index 4f2ead2052ccbc3a5036a13625a4b47d3eaea022..3da6a9a1b0d257080c8287bf23a6639085b1ece1 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -178,7 +178,7 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) { result = strcpy_s(msg.command, maxCommandSize, "boot_updater"); msg.command[maxCommandSize] = 0; - } else if (rebootTarget == "flash" && strcmp(msg.command, "flash") != 0) { + } else if (rebootTarget == "flashd" && strcmp(msg.command, "flashd") != 0) { result = strcpy_s(msg.command, maxCommandSize, "boot_flash"); msg.command[maxCommandSize] = 0; } else if (rebootTarget == "bootloader" && strcmp(msg.command, "boot_loader") != 0) { @@ -190,6 +190,8 @@ void DoReboot(const std::string& rebootTarget, const std::string &extData) result = strcpy_s(msg.update, MAX_UPDATE_SIZE - 1, extData.c_str()); UPDATER_ERROR_CHECK(result == 0, "Failed to copy update", return); msg.update[MAX_UPDATE_SIZE - 1] = 0; + } else { + UPDATER_ERROR_CHECK(!memset_s(msg.update, MAX_UPDATE_SIZE, 0, MAX_UPDATE_SIZE), "Memset_s failed", return); } if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error";