diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1ec17bb600724cbdc5da12fb0aa3beb849bc9ab2 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,19 @@ +# 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. + +import("//build/ohos.gni") + +group("unittest") { + testonly = true + deps = [ "test/unittest:updater_unittest" ] +} diff --git a/LICENSE b/LICENSE index a3a34c888af19fb9b68d575aa1d3fa8288cd4d1e..a2f2620598accbbfc72fbc0622a66ca27fc839fc 100755 --- a/LICENSE +++ b/LICENSE @@ -11,22 +11,6 @@ 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. -*************************************************************** -libsparse, it is derived from the following: -https://android.googlesource.com/platform/system/core/ -version 10.0.0_r2 -*************************************************************** -Copyright (C) 2012, The Android Open Source Project - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. - -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. - *************************************************************** bsdiff, it is derived from the following: @@ -235,4 +219,4 @@ version 4.3 incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. - END OF TERMS AND CONDITIONS \ No newline at end of file + END OF TERMS AND CONDITIONS diff --git a/OAT.xml b/OAT.xml index e52288de5741b09b03f9e8201948e18399ea5f8e..9aa92b4fc8019a95b92556af9c426dce32b3026b 100755 --- a/OAT.xml +++ b/OAT.xml @@ -65,14 +65,23 @@ Note:If the text contains special characters, please escape them according to th - + - - - - + + + + + + + + + + + + + diff --git a/README.md b/README.md index 7953eb83c86adbbbf032d232136ff9b4d66e9d4c..cdf37172fc7b0933d77e463e89bb7fe941c612f2 100755 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ## Introduction -The updater runs in the recovery partition. It reads the misc partition information to obtain the update package status and verifies the update package to ensure that the update package is valid. Then, the updater parses the executable program from the update package, creates a subprocess, and starts the update program. After that, update operations will be automatically implemented by the update script. +The updater runs in the updater partition. It reads the misc partition information to obtain the update package status and verifies the update package to ensure that the update package is valid. Then, the updater parses the executable program from the update package, creates a subprocess, and starts the update program. After that, update operations will be automatically implemented by the update script. ## Directory Structure @@ -37,11 +37,11 @@ base/update/updater/ ### Usage Guidelines -The updater runs in the recovery partition. To ensure proper functioning of the updater, perform the following operations: +The updater runs in the updater partition. To ensure proper functioning of the updater, perform the following operations: -1. Create a recovery partition. +1. Create a updater partition. -The recovery partition is independent of other partitions. It is recommended that the size of the recovery partition be greater than or equal to 20 MB. The recovery partition image is an ext4 file system. Ensure that the **config** option of the ext4 file system in the system kernel is enabled. +The updater partition is independent of other partitions. It is recommended that the size of the updater partition be greater than or equal to 20 MB. The updater partition image is an ext4 file system. Ensure that the **config** option of the ext4 file system in the system kernel is enabled. 2. Create the misc partition. @@ -53,7 +53,7 @@ During the update process, the updater needs to operate the partitions through t 4. Start the updater. -The init process in the recovery partition has an independent configuration file named **init.cfg**. The startup configuration of the updater is stored in this file. +The init process in the updater partition has an independent configuration file named **init.cfg**. The startup configuration of the updater is stored in this file. 5. Compile the updater. @@ -78,7 +78,7 @@ For example, to add the updater for Hi3516D V300, add the following code to the "updater:updater":{}, ``` -6. Compile the recovery partition image. +6. Compile the updater partition image. Add the compilation configuration to the **build\_updater\_image.sh** script, which is stored in the **build** repository and called by the OpenHarmony compilation system. diff --git a/README_zh.md b/README_zh.md index 62c79a58d6bb97d11e1446188f4fb0827a9b4e50..e8900d27e211e017119d5b88ec19cf2c07e74640 100755 --- a/README_zh.md +++ b/README_zh.md @@ -9,7 +9,7 @@ ## 简介 -升级包安装组件运行在recovery分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。 +升级包安装组件运行在updater分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。 ## 目录 @@ -37,11 +37,11 @@ base/update/updater/ ### 使用说明 -升级包安装组件运行在recovery分区里,需要如下的操作 +升级包安装组件运行在updater分区里,需要如下的操作 -1、创建recovery分区 +1、创建updater分区 -recovery是一个独立的分区,分区大小建议不小于20MB。recovery分区镜像是ext4 格式文件系统。确保系统内核ext4 文件系统的config 是打开状态。 +updater是一个独立的分区,分区大小建议不小于20MB。updater分区镜像是ext4 格式文件系统。确保系统内核ext4 文件系统的config 是打开状态。 2、创建misc分区 @@ -53,7 +53,7 @@ misc 分区中存储了升级子系统在升级过程中需要的元数据\(meta 4、升级包安装组件启动 -recovery分区的init 进程有单独的配置文件 init.cfg,升级包安装进程启动配置在该文件中。 +updater分区的init 进程有单独的配置文件 init.cfg,升级包安装进程启动配置在该文件中。 5、升级包安装组件编译 @@ -78,7 +78,7 @@ b、 产品中添加需要编译的组件 "updater:updater":{}, ``` -6、recovery分区镜像编译 +6、updater分区镜像编译 编译配置在build仓下,build\_updater\_image.sh 脚本中,该脚本由OHOS 编译系统调用。 diff --git a/bundle.json b/bundle.json new file mode 100644 index 0000000000000000000000000000000000000000..42a5a0fd08797af9c54fc48ca00367743f59eb00 --- /dev/null +++ b/bundle.json @@ -0,0 +1,118 @@ +{ + "name": "@ohos/update_updater", + "version": "3.1", + "description": "升级包安装组件运行在recovery分区,其功能主要包括读取misc分区信息获取升级包状态,对升级包进行校验,确保升级包合法有效;然后从升级包中解析出升级的可执行程序,创建子进程并启动升级程序。具体升级的动作由升级脚本控制。", + "homePage": "https://gitee.com/openharmony", + "license": "Apache License 2.0", + "repository": "https://gitee.com/openharmony/update_updater", + "domain": "os", + "language": "", + "publishAs": "code-segment", + "private": false, + "scripts": {}, + "tags": [ + "base" + ], + "keywords": [ + "update", + "updater" + ], + "envs": {}, + "dirs": {}, + "author": { + "name": "", + "email": "", + "url": "" + }, + "contributors": [ + { + "name": "", + "email": "", + "url": "" + } + ], + "segment": { + "destPath": "base/update/updater" + }, + "component": { + "name": "updater", + "subsystem": "updater", + "syscap": [], + "features": [], + "adapted_system_type": [ "standard" ], + "rom": "", + "ram": "", + "deps": { + "components": [ + "startup_init_lite", + "startup_syspara_lite", + "developtools_hdc_standard", + "utils_native", + "drivers_peripheral" + ], + "third_party": [ + "third_party_bounds_checking_function", + "third_party_bzip2", + "third_party_libdrm", + "third_party_lz4", + "third_party_openssl", + "third_party_libusb", + "third_party_zlib", + "third_party_libuv", + "third_party_cJSON", + "third_party_libpng" + ] + }, + "build": { + "sub_component": [ + "//base/update/updater/resources:updater_resources", + "//base/update/updater/services:updater_etc", + "//base/update/updater/services/package:libupdaterpackage", + "//base/update/updater/services/script:libupdaterscript", + "//base/update/updater/services/log:libupdaterlog", + "//base/update/updater/services/updater_binary:updater_binary", + "//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", + "//base/update/updater/services/diffpatch/patch:libpatch", + "//base/update/updater/services/diffpatch/diff:libdiff", + "//base/update/updater/services/ui:libui" + ], + "inner_kits": [ + { + "name": "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", + "header": { + "header_files": [ + "misc_info/misc_info.h" + ], + "header_base": "//base/update/updater/interfaces/kits/include" + } + }, + { + "name": "//base/update/updater/interfaces/kits/packages:libpackageExt", + "header": { + "header_files": [ + "package/package.h" + ], + "header_base": "//base/update/updater/interfaces/kits/include" + } + }, + { + "name": "//base/update/updater/interfaces/kits/updaterkits:libupdaterkits", + "header": { + "header_files": [ + "updaterkits/updaterkits.h" + ], + "header_base": "//base/update/updater/interfaces/kits/include" + } + } + ], + "test": [] + } + } +} + diff --git a/interfaces/kits/include/misc_info/misc_info.h b/interfaces/kits/include/misc_info/misc_info.h index 8b260fcaa90b53737c65521daf8b234490981b10..38f781fd0587162ee6c24bec5f31138cee882cbe 100755 --- a/interfaces/kits/include/misc_info/misc_info.h +++ b/interfaces/kits/include/misc_info/misc_info.h @@ -23,9 +23,9 @@ namespace updater { constexpr int MAX_COMMAND_SIZE = 20; constexpr int MAX_UPDATE_SIZE = 100; +constexpr int MAX_LOGO_SIZE = 1024 * 2038; - -// misc partition offset definition. max size of misc is 1MB, do not overflow. +// misc partition offset definition. max size of misc is 2MB, do not overflow. constexpr off_t MISC_BASE_OFFSET = 0; constexpr off_t MISC_UPDATE_MESSAGE_OFFSET = MISC_BASE_OFFSET; @@ -37,6 +37,9 @@ constexpr off_t MISC_PARTITION_RECORD_SIZE = 1024; constexpr off_t MISC_RECORD_UPDATE_PARTITIONS_OFFSET = MISC_PARTITION_RECORD_OFFSET + MISC_PARTITION_RECORD_SIZE; constexpr off_t MISC_RECORD_UPDATE_PARTITIONS_SIZE = 256; +constexpr off_t MISC_RECORD_MISC_PARTITIONS_OFFSET = 1536; +constexpr off_t MISC_RECORD_MISC_PARTITIONS_SIZE = 1024 * 2038; + struct UpdateMessage { char command[MAX_COMMAND_SIZE]; char update[MAX_UPDATE_SIZE]; diff --git a/interfaces/kits/misc_info/BUILD.gn b/interfaces/kits/misc_info/BUILD.gn index 51b347ca1fafc8813e2c287910639fd3867c3a75..37a3aedcd846fe3a88e63f358d36b6f31e9fbbb6 100755 --- a/interfaces/kits/misc_info/BUILD.gn +++ b/interfaces/kits/misc_info/BUILD.gn @@ -28,4 +28,9 @@ ohos_static_library("libmiscinfo") { "//base/update/updater/services/log:libupdaterlog", "//third_party/bounds_checking_function:libsec_static", ] + + external_deps = [ "init:libbegetutil" ] + + subsystem_name = "updater" + part_name = "updater" } diff --git a/interfaces/kits/packages/BUILD.gn b/interfaces/kits/packages/BUILD.gn index 19933e10b5b1169ced1d878659ba7e5060fac581..9d8efcd3da25bbf9ac63d66e60a5fa59479456df 100755 --- a/interfaces/kits/packages/BUILD.gn +++ b/interfaces/kits/packages/BUILD.gn @@ -29,8 +29,10 @@ ohos_static_library("libpackageExt") { "//base/update/updater/services/package:libupdaterpackage", "//third_party/bounds_checking_function:libsec_static", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/interfaces/kits/updaterkits/BUILD.gn b/interfaces/kits/updaterkits/BUILD.gn index 6cd54b647b212e9e5d3d13b30e3deed2757aaf9d..2c68114f85aefa181ba731b310200d73021ff3ca 100755 --- a/interfaces/kits/updaterkits/BUILD.gn +++ b/interfaces/kits/updaterkits/BUILD.gn @@ -29,4 +29,8 @@ ohos_static_library("libupdaterkits") { "//base/update/updater/utils:libutils", "//third_party/bounds_checking_function:libsec_static", ] + + external_deps = [ "init:libbegetutil" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/interfaces/kits/updaterkits/updaterkits.cpp b/interfaces/kits/updaterkits/updaterkits.cpp index 60ac4c5e885532adde38c32d108fdb2ffa47a7d0..227621f56eea5211cd0c3b2acbc576a027af477d 100755 --- a/interfaces/kits/updaterkits/updaterkits.cpp +++ b/interfaces/kits/updaterkits/updaterkits.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "misc_info/misc_info.h" #include "parameters.h" #include "securec.h" @@ -38,12 +39,8 @@ static bool WriteToMiscAndRebootToUpdater(const std::string &miscFile, #ifndef UPDATER_UT 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); - if (!bRet) { - std::cout << "WriteToMiscAndRebootToUpdater SetParameter failed, errno: " << errno << std::endl; - return false; - } + void(snprintf_s(updateCmd, propertyMaxSize, propertyMaxSize - 1, "updater:%s", updateMsg.update)); + DoReboot(updateCmd); while (true) { pause(); } diff --git a/ohos.build b/ohos.build deleted file mode 100644 index 65c0a527fcb61a6c2e8772bcf88c691e7de01fa9..0000000000000000000000000000000000000000 --- a/ohos.build +++ /dev/null @@ -1,36 +0,0 @@ -{ - "subsystem": "updater", - "parts": { - "updater": { - "module_list": [ - "//base/update/updater/resources:updater_resources", - "//base/update/updater/services:updater_etc", - "//base/update/updater/services/package:libupdaterpackage", - "//base/update/updater/services/script:libupdaterscript", - "//base/update/updater/services/log:libupdaterlog", - "//base/update/updater/services/updater_binary:updater_binary", - "//base/update/updater/services:updater", - "//base/update/updater/services/applypatch:libapplypatch", - "//base/update/updater/services/fs_manager:libfsmanager", - "//base/update/updater/utils:libutils", - "//base/update/updater/utils:updater_reboot", - "//base/update/updater/utils:write_updater", - "//base/update/updater/services/diffpatch/patch:libpatch", - "//base/update/updater/services/diffpatch/diff:libdiff", - "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", - "//base/update/updater/interfaces/kits/packages:libpackageExt", - "//base/update/updater/interfaces/kits/updaterkits:libupdaterkits", - "//base/update/updateservice/client:update", - "//base/update/updateservice/engine:updateservice", - "//base/update/updateservice/engine:updater_sa.rc", - "//base/update/updateservice/engine/sa_profile:updater_sa_profile", - "//base/update/updateservice/interfaces/innerkits/engine:updateservicekits", - "//base/update/updater/services/ui:libui", - "//third_party/libdrm:libdrm", - "//third_party/e2fsprogs:e2fsprogs" - ] - } - } -} - - diff --git a/prebuild/ohos-sdk/windows/toolchains/ohflash.exe b/prebuild/ohos-sdk/windows/toolchains/ohflash.exe new file mode 100755 index 0000000000000000000000000000000000000000..68350a9e3f7b961a474c1ab1826f5a63a846c178 --- /dev/null +++ b/prebuild/ohos-sdk/windows/toolchains/ohflash.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3fc6530c09c0db909e841a802a1eee8eaf92f2ff7ab0388b7edbeac5b8531ae +size 3297792 diff --git a/services/BUILD.gn b/services/BUILD.gn old mode 100644 new mode 100755 index 964704d76c27573da054c477eff50450a1d4a7f5..a82b38f5aef2a220642ab9e557c4632261c61efd --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -21,16 +21,27 @@ ohos_prebuilt_etc("updater_init.cfg") { part_name = "updater" } +ohos_prebuilt_etc("updater_usb_init.cfg") { + source = "//base/update/updater/services/etc/init.usb.cfg" + install_images = [ "updater" ] + part_name = "updater" +} + +ohos_prebuilt_etc("updater_init_usb_configfs.cfg") { + source = "//base/update/updater/services/etc/init.usb.configfs.cfg" + install_images = [ "updater" ] + part_name = "updater" +} + ohos_prebuilt_etc("signing_cert.crt") { - source = - "//device/hisilicon/hi3516dv300/build/updater_config/signing_cert.crt" + source = "//device/board/hisilicon/hispark_taurus/linux/updater/config/signing_cert.crt" module_install_dir = "certificate" install_images = [ "updater" ] part_name = "updater" } ohos_prebuilt_etc("fstab.updater") { - source = "//device/hisilicon/hi3516dv300/build/vendor/etc/fstab.updater" + source = "//device/board/hisilicon/hispark_taurus/linux/updater/config/fstab.updater" install_images = [ "updater" ] part_name = "updater" } @@ -40,6 +51,8 @@ group("updater_etc") { ":fstab.updater", ":signing_cert.crt", ":updater_init.cfg", + ":updater_init_usb_configfs.cfg", + ":updater_usb_init.cfg", ] } @@ -49,12 +62,13 @@ ohos_executable("updater") { "main.cpp", "updater.cpp", "updater_main.cpp", + "updater_utils.cpp", ] include_dirs = [ "include", "$SUBSYSTEM_DIR/utils/include", - "$SUBSYSTEM_DIR/interfaces/kits/include/", + "$SUBSYSTEM_DIR/interfaces/kits/include", "//third_party/bounds_checking_function/include", "//base/update/updater/services/include/package", "//base/update/updater/services/package/pkg_manager", @@ -79,6 +93,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", @@ -88,10 +103,12 @@ ohos_executable("updater") { "//third_party/bzip2:libbz2", "//third_party/libdrm:libdrm", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] + + external_deps = [ "init:libbegetutil" ] install_images = [ "updater" ] install_enable = true part_name = "updater" diff --git a/services/applypatch/BUILD.gn b/services/applypatch/BUILD.gn index 8d8d872562b1d86440ffb7b5216ae2a3a32e0266..ec459547cd3c18d3424584c3aba5b7d68d5d1cc8 100644 --- a/services/applypatch/BUILD.gn +++ b/services/applypatch/BUILD.gn @@ -47,4 +47,7 @@ ohos_static_library("libapplypatch") { "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", ] + external_deps = [ "init:libbegetutil" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/applypatch/block_set.cpp b/services/applypatch/block_set.cpp index b1670a933cf21730069449cd4431a5ed674b67b4..b267cfb72a0f6bb955690fadd313cef42ad6c332 100644 --- a/services/applypatch/block_set.cpp +++ b/services/applypatch/block_set.cpp @@ -228,7 +228,7 @@ int32_t BlockSet::LoadSourceBuffer(const Command &cmd, size_t &pos, std::vector< LOG(INFO) << "new start to read source block ..."; UPDATER_CHECK_ONLY_RETURN(srcBlk.ReadDataFromBlock(cmd.GetFileDescriptor(), sourceBuffer) > 0, return -1); std::string nextArgv = cmd.GetArgumentByPos(pos++); - UPDATER_CHECK_ONLY_RETURN(nextArgv != "", return 0); + UPDATER_CHECK_ONLY_RETURN(nextArgv != "", return 1); BlockSet locations; locations.ParserAndInsert(nextArgv); MoveBlock(sourceBuffer, locations, sourceBuffer); diff --git a/services/applypatch/partition_record.cpp b/services/applypatch/partition_record.cpp index 9d7581762a1b1eb150de742286d0a961c78b0514..e6de89be5d0fa02396bba601cada9d8be9a69026 100644 --- a/services/applypatch/partition_record.cpp +++ b/services/applypatch/partition_record.cpp @@ -31,9 +31,9 @@ bool PartitionRecord::IsPartitionUpdated(const std::string &partitionName) { auto miscBlockDevice = GetMiscPartitionPath(); uint8_t buffer[PARTITION_UPDATER_RECORD_MSG_SIZE]; - char *realPath = realpath(miscBlockDevice.c_str(), NULL); - UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false); if (!miscBlockDevice.empty()) { + char *realPath = realpath(miscBlockDevice.c_str(), NULL); + UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false); int fd = open(realPath, O_RDONLY | O_EXCL | O_CLOEXEC | O_BINARY); free(realPath); UPDATER_FILE_CHECK(fd >= 0, "PartitionRecord: Open misc to recording partition failed", return false); @@ -60,9 +60,9 @@ bool PartitionRecord::IsPartitionUpdated(const std::string &partitionName) bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionName, bool updated) { auto miscBlockDevice = GetMiscPartitionPath(); - char *realPath = realpath(miscBlockDevice.c_str(), NULL); - UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false); if (!miscBlockDevice.empty()) { + char *realPath = realpath(miscBlockDevice.c_str(), NULL); + UPDATER_FILE_CHECK(realPath != nullptr, "realPath is NULL", return false); int fd = open(realPath, O_RDWR | O_EXCL | O_CLOEXEC | O_BINARY); free(realPath); UPDATER_FILE_CHECK(fd >= 0, "PartitionRecord: Open misc to recording partition failed", return false); @@ -76,6 +76,8 @@ bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionNa UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_START + offset_, SEEK_SET) >= 0, "PartitionRecord: Seek misc to specific offset failed", fd, return false); if (offset_ + sizeof(PartitionRecordInfo) < PARTITION_UPDATER_RECORD_SIZE) { + UPDATER_CHECK_FILE_OP(memset_s(&info_, sizeof(info_), 0, sizeof(info_)) == 0, + "PartitionRecord: clear partition info failed", fd, return false); UPDATER_CHECK_FILE_OP(!strncpy_s(info_.partitionName, PARTITION_NAME_LEN, partitionName.c_str(), PARTITION_NAME_LEN - 1), "PartitionRecord: strncpy_s failed", fd, return false); info_.updated = updated; @@ -85,7 +87,7 @@ bool PartitionRecord::RecordPartitionUpdateStatus(const std::string &partitionNa UPDATER_CHECK_FILE_OP(lseek(fd, PARTITION_RECORD_OFFSET, SEEK_SET) >= 0, "PartitionRecord: Seek misc to record offset failed", fd, return false); UPDATER_CHECK_FILE_OP(write(fd, &offset_, sizeof(off_t)) == sizeof(off_t), - "PartitionRecord: Seek misc to record offset failed", fd, return false); + "PartitionRecord: write misc to record offset failed", fd, return false); LOG(DEBUG) << "PartitionRecord: offset is " << offset_; } else { LOG(WARNING) << "PartitionRecord: partition record overflow, offset = " << offset_; diff --git a/services/applypatch/transfer_manager.cpp b/services/applypatch/transfer_manager.cpp index bb2746c1b9b9a4ebbc5fd1406b4ec699d3c8352a..f2281560815dbe6222e4beafd35b3bade0b040d2 100644 --- a/services/applypatch/transfer_manager.cpp +++ b/services/applypatch/transfer_manager.cpp @@ -58,12 +58,13 @@ bool TransferManager::CommandsParser(int fd, const std::vector &con globalParams->blockCount = utils::String2Int(*ct++, utils::N_DEC); globalParams->maxEntries = utils::String2Int(*ct++, utils::N_DEC); globalParams->maxBlocks = utils::String2Int(*ct++, utils::N_DEC); - size_t totalSize = globalParams->maxBlocks * globalParams->blockCount; + size_t totalSize = globalParams->blockCount; std::string retryCmd = ""; if (globalParams != nullptr && globalParams->env != nullptr && globalParams->env->IsRetry()) { retryCmd = ReloadForRetry(); } std::unique_ptr cmd; + int initBlock = 0; while (ct != context.end()) { cmd = std::make_unique(); UPDATER_ERROR_CHECK(cmd != nullptr, "Failed to parse command line.", return false); @@ -82,18 +83,17 @@ bool TransferManager::CommandsParser(int fd, const std::vector &con cmd->SetFileDescriptor(fd); std::unique_ptr cf = CommandFunctionFactory::GetCommandFunction(cmd->GetCommandType()); UPDATER_ERROR_CHECK(cf != nullptr, "Failed to get cmd exec", return false); - CommandResult ret = cf->Execute(const_cast(*cmd.get())); + CommandResult ret = cf->Execute(const_cast(*cmd.get())); CommandFunctionFactory::ReleaseCommandFunction(cf); if (CheckResult(ret, cmd->GetCommandLine(), cmd->GetCommandType()) == false) { return false; } - - bool typeResult = cmd->GetCommandType() == CommandType::NEW || - cmd->GetCommandType() == CommandType::IMGDIFF || - cmd->GetCommandType() == CommandType::BSDIFF; - if (totalSize != 0 && globalParams->env != nullptr && typeResult) { - globalParams->env->PostMessage("set_progress", - std::to_string((float)globalParams->written / totalSize)); + if (initBlock == 0) { + initBlock = globalParams->written; + } + if (totalSize != 0 && globalParams->env != nullptr && NeedSetProgress(cmd->GetCommandType())) { + globalParams->env->PostMessage("set_progress", + std::to_string((float)(globalParams->written - initBlock) / totalSize)); } LOG(INFO) << "Running command : " << cmd->GetArgumentByPos(0) << " success"; } @@ -112,7 +112,7 @@ void TransferManager::Init() bool TransferManager::RegisterForRetry(const std::string &cmd) { - std::string path = globalParams->storeBase + "/" + "retry_flag"; + std::string path = globalParams->retryFile; int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); UPDATER_ERROR_CHECK(fd != -1, "Failed to create", return false); UPDATER_ERROR_CHECK(fchown(fd, O_USER_GROUP_ID, O_USER_GROUP_ID) == 0, @@ -121,13 +121,12 @@ bool TransferManager::RegisterForRetry(const std::string &cmd) UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Write retry flag error"); fsync(fd); close(fd); - return ret; } std::string TransferManager::ReloadForRetry() const { - std::string path = globalParams->storeBase + "/" + "retry_flag"; + std::string path = globalParams->retryFile; int fd = open(path.c_str(), O_RDONLY); UPDATER_ERROR_CHECK(fd >= 0, "Failed to open", return ""); (void)lseek(fd, 0, SEEK_SET); @@ -137,6 +136,14 @@ std::string TransferManager::ReloadForRetry() const return cmd; } +bool TransferManager::NeedSetProgress(const CommandType &type) +{ + return type == CommandType::NEW || + type == CommandType::IMGDIFF || + type == CommandType::BSDIFF || + type == CommandType::ZERO; +} + bool TransferManager::CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type) { switch (result) { @@ -149,12 +156,10 @@ bool TransferManager::CheckResult(const CommandResult result, const std::string LOG(INFO) << "Running command need retry!"; UPDATER_CHECK_ONLY_RETURN(!globalParams->env, globalParams->env->PostMessage("retry_update", cmd)); return false; - break; case FAILED: default: LOG(ERROR) << "Running command failed"; return false; - break; } return true; } diff --git a/services/diffpatch/bzip2/zip_adapter.h b/services/diffpatch/bzip2/zip_adapter.h index 4385bf197e8e7c7411aa03d027e7dc1faa6936b1..090bddef338ff0a24d399697e81535b63549f0e8 100644 --- a/services/diffpatch/bzip2/zip_adapter.h +++ b/services/diffpatch/bzip2/zip_adapter.h @@ -40,7 +40,7 @@ public: private: std::vector buffer_ {}; UpdatePatchWriterPtr outStream_; - z_stream zstream_; + z_stream zstream_ {0}; size_t offset_; int32_t level_ {0}; diff --git a/services/diffpatch/diff/BUILD.gn b/services/diffpatch/diff/BUILD.gn index e9e37cdee270ad35859ae98f8105d1d423cdff5b..c980ca099717c89aa3d83201ae30e2c039a9934b 100644 --- a/services/diffpatch/diff/BUILD.gn +++ b/services/diffpatch/diff/BUILD.gn @@ -46,4 +46,7 @@ ohos_static_library("libdiff") { "//third_party/bzip2:libbz2", ] configs = [ ":diff_config" ] + + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/diffpatch/diff/blocks_diff.cpp b/services/diffpatch/diff/blocks_diff.cpp index d579dbd9a3e68d23c4dccba99744435b07b47dab..2a68f28cf9f3cbbcedebd5c2721b093814a7c66a 100644 --- a/services/diffpatch/diff/blocks_diff.cpp +++ b/services/diffpatch/diff/blocks_diff.cpp @@ -237,7 +237,7 @@ void BlocksDiff::ComputeLength(const BlockBuffer &newInfo, int64_t i = 0; int64_t s = 0; int64_t tmp = 0; - for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length)); ) { + for (; ((lastScan_ + i) < currentOffset_) && ((lastPos_ + i) < static_cast(oldInfo.length));) { if (oldInfo.buffer[lastPos_ + i] == newInfo.buffer[lastScan_ + i]) { s++; } @@ -413,7 +413,7 @@ void SuffixArray::Init(const BlockBuffer &oldInfo) DataType len = 0; for (h = 1; suffixArray_[0] != -(static_cast(oldInfo.length) + 1); h += h) { len = 0; - for (i = 0; i < (static_cast(oldInfo.length) + 1); ) { + for (i = 0; i < (static_cast(oldInfo.length) + 1);) { if (suffixArray_[i] < 0) { len -= suffixArray_[i]; i -= suffixArray_[i]; 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/diffpatch/patch/BUILD.gn b/services/diffpatch/patch/BUILD.gn index 0a28158aa93ee6af534a8ef9af6c58e846ffdd52..912a88b2e9b70e5d3794ee1cb2fdd6bd141de3bd 100644 --- a/services/diffpatch/patch/BUILD.gn +++ b/services/diffpatch/patch/BUILD.gn @@ -52,4 +52,6 @@ ohos_static_library("libpatch") { ] configs = [ ":patch_config" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/etc/init.cfg b/services/etc/init.cfg index 5615a7d628505244d6ba5af29f7229e596c2a32f..c69e192aa5112637b528b009ebf6f69cb579ca94 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -13,18 +13,45 @@ "cmds" : [ "mkdir /system", "mkdir /vendor", - "mkdir /odm", - "mkdir /hos", "mkdir /tmp", + "mkdir /param", "mount tmpfs tmpfs /tmp", "chown 0 2000 /tmp", - "chmod 0755 /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", + "mkdir /config 0770 shell shell", + "mount configfs none /config", + "mkdir /config/usb_gadget/g1 0770 shell shell", + "write /config/usb_gadget/g1/idVendor 0x12D1", + "write /config/usb_gadget/g1/idProduct 0x5000", + "write /config/usb_gadget/g1/os_desc/use 1", + "write /config/usb_gadget/g1/bcdDevice 0x0223", + "write /config/usb_gadget/g1/bcdUSB 0x0200", + "mkdir /config/usb_gadget/g1/strings/0x409 0770", + "copy /sys/block/mmcblk0/device/cid /config/usb_gadget/g1/strings/0x409/serialnumber", + "write /config/usb_gadget/g1/strings/0x409/manufacturer HISILICON", + "write /config/usb_gadget/g1/strings/0x409/product \"HDC Device\"", + "mkdir /config/usb_gadget/g1/functions/ffs.hdc", + "mkdir /config/usb_gadget/g1/configs/b.1 0770 shell shell", + "mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770 shell shell", + "write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1", + "write /config/usb_gadget/g1/os_desc/qw_sign MSFT100", + "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" ] }, { "name" : "post-init", "cmds" : [ - "start updater", - "start shell" + "start shell", + "start updater" ] } ], @@ -35,14 +62,12 @@ "gid" : 2000, "once" : 0, "importance" : 0, - "console" : 1, - "caps" : [4294967295] + "console" : 1 }, { "name" : "updater", "path" : ["/bin/updater"], "uid" : 0, "gid" : 0, - "once" : 1, "importance" : 0, "caps" : [0, 1] }, { @@ -52,7 +77,24 @@ "gid" : 2000, "once" : 0, "importance" : 0, - "caps" : [0, 1] + "caps" : [0, 1], + "socket" : [{ + "name" : "ueventd", + "family" : "AF_NETLINK", + "type" : "SOCK_DGRAM", + "protocol" : "NETLINK_KOBJECT_UEVENT", + "permissions" : "0660", + "uid" : "0", + "gid" : "2000", + "option" : [ + "SOCKET_OPTION_PASSCRED", + "SOCKET_OPTION_RCVBUFFORCE", + "SOCK_CLOEXEC", + "SOCK_NONBLOCK" + ] + }], + "critical" : [ 0, 15, 5], + "ondemand" : true } ] } diff --git a/services/etc/init.usb.cfg b/services/etc/init.usb.cfg new file mode 100755 index 0000000000000000000000000000000000000000..1a3072219b4bc774fbfc5b69fc6a755767b26c8c --- /dev/null +++ b/services/etc/init.usb.cfg @@ -0,0 +1,15 @@ +{ + "jobs" : [{ + "name" : "boot", + "cmds" : [ + "setparam sys.usb.configfs 0" + ] + }, { + "name" : "boot && param:persist.sys.usb.config=*", + "condition" : "boot && persist.sys.usb.config=*", + "cmds" : [ + "setparam sys.usb.config ${persist.sys.usb.config}" + ] + } + ] +} diff --git a/services/etc/init.usb.configfs.cfg b/services/etc/init.usb.configfs.cfg new file mode 100755 index 0000000000000000000000000000000000000000..4474b0989ec5a86369126a73fe228eecfc113192 --- /dev/null +++ b/services/etc/init.usb.configfs.cfg @@ -0,0 +1,25 @@ +{ + "jobs" : [{ + "name" : "param:sys.usb.config=none && param:sys.usb.configfs=1", + "condition" : "sys.usb.config=none && sys.usb.configfs=1", + "cmds" : [ + "write /config/usb_gadget/g1/UDC none", + "setparam sys.usb.ffs.ready 0", + "write /config/usb_gadget/g1/bDeviceClass 0", + "write /config/usb_gadget/g1/bDeviceSubClass 0", + "write /config/usb_gadget/g1/bDeviceProtocol 0", + "rm /config/usb_gadget/g1/configs/b.1/f1", + "setparam sys.usb.state ${sys.usb.config}" + ] + }, { + "name" : "param:sys.usb.ffs.ready=1 && param:sys.usb.config=hdc && param:sys.usb.configfs=1", + "condition" : "sys.usb.ffs.ready=1 && sys.usb.config=hdc && sys.usb.configfs=1", + "cmds" : [ + "write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration hdc", + "symlink /config/usb_gadget/g1/functions/ffs.hdc /config/usb_gadget/g1/configs/b.1/f1", + "write /config/usb_gadget/g1/UDC ${sys.usb.controller}", + "setparam sys.usb.state ${sys.usb.config}" + ] + } + ] +} diff --git a/services/flashd/BUILD.gn b/services/flashd/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..f38b79b3e8b75a487b8addf8e31224ec1788e730 --- /dev/null +++ b/services/flashd/BUILD.gn @@ -0,0 +1,241 @@ +# 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. + +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) { + external_deps = [ + "init:libbegetutil", + "startup_l2: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", + "//third_party/bounds_checking_function/include", + "//third_party/lz4/lib", + "//third_party/openssl/include", + "//third_party/libuv", + ] + + subsystem_name = "updater" + part_name = "updater" +} + +ohos_static_library("libflashd") { + sources = [ + "//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/partition.cpp", + "//base/update/updater/services/updater_binary/update_image_block.cpp", + "//base/update/updater/services/updater_binary/update_partitions.cpp", + "//base/update/updater/services/updater_binary/update_processor.cpp", + ] + + defines = [ + "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", + "//base/update/updater/services/fs_manager:libfsmanager", + "//base/update/updater/services/log:libupdaterlog", + "//base/update/updater/services/package:libupdaterpackage", + "//base/update/updater/services/script:libupdaterscript", + "//base/update/updater/utils:libutils", + "//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/zlib:libz", + "//utils/native/base:utils", + ] + + include_dirs = [ + "${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", + "//base/update/updater/services/include/log", + "//base/update/updater/services/include", + "//base/update/updater/utils/include", + "//third_party/bounds_checking_function/include", + "//third_party/cJSON", + "//third_party/openssl/include", + "//third_party/lz4/lib", + "//third_party/libuv", + ] + + external_deps = [ "init:libbegetutil" ] + + 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/bounds_checking_function:libsec_static", + "//third_party/libusb:libusb", + "//third_party/libuv:uv_static", + "//third_party/lz4:liblz4_static", + "//third_party/openssl:libcrypto_static", + ] + + deps += [ "//third_party/libusb:libusb" ] + + include_dirs = [ + "${FLASHD_PATH}/host", + "${HDC_PATH}/host", + "${FLASHD_PATH}/common", + "${HDC_PATH}/common", + "//third_party/bounds_checking_function/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/blockdevice.cpp b/services/flashd/blockdevice.cpp new file mode 100755 index 0000000000000000000000000000000000000000..02d2d23973d318ff4eae785be8e58d18a2b2ed86 --- /dev/null +++ b/services/flashd/blockdevice.cpp @@ -0,0 +1,55 @@ +/* + * 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 "blockdevice.h" +#include +#include +#include +#include +#include +#include +#include "flash_service.h" + +namespace flashd { +int BlockDevice::Load() +{ + struct stat devStat {}; + int ret = stat(devPath_.c_str(), &devStat); + FLASHING_CHECK(ret != -1, return -1, "Failed to state %s", devPath_.c_str()); + + const std::string devName = GetDeviceName(); + std::string size = ReadDeviceSysInfo("size"); + FLASHING_CHECK(!size.empty(), return 0, "Failed to read dev size"); + devSize_ = atol(size.c_str()); + sectorSize_ = SECTOR_SIZE_DEFAULT; + physSectorSize_ = SECTOR_SIZE_DEFAULT; + return 0; +} + +const std::string BlockDevice::GetDeviceName() +{ + std::string::size_type pos = devPath_.find_last_of('/') + 1; + return devPath_.substr(pos, devPath_.size() - pos); +} + +std::string BlockDevice::ReadDeviceSysInfo(const std::string &type) +{ + std::vector buffer(DEVICE_PATH_SIZE, 0); + int ret = snprintf_s(buffer.data(), DEVICE_PATH_SIZE, DEVICE_PATH_SIZE - 1, + "/sys/block/%s/%s", GetDeviceName().c_str(), type.c_str()); + FLASHING_CHECK(ret != -1, return "", "Failed to snprintf_s %s", devPath_.c_str()); + std::vector table; + return FlashService::ReadSysInfo(buffer.data(), type, table); +} +} // namespace flashd \ No newline at end of file diff --git a/services/include/fs_manager/fstab.h b/services/flashd/blockdevice.h old mode 100644 new mode 100755 similarity index 40% rename from services/include/fs_manager/fstab.h rename to services/flashd/blockdevice.h index 4cf3b750daafe3ab31419abca3d9edeb3de7068a..3533a5861dcd1464fd856ad7726bffd486680870 --- a/services/include/fs_manager/fstab.h +++ b/services/flashd/blockdevice.h @@ -1,42 +1,51 @@ -/* - * 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_FS_MANAGER_FSTAB_H -#define __UPDATER_FS_MANAGER_FSTAB_H -#include -#include -#include - -namespace updater { -/* Fs manager flags definition */ -#define FS_MANAGER_CHECK 0x00000001 -#define FS_MANAGER_WAIT 0x00000002 - -#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT) -#define FS_MANAGER_FLAGS_ENABLED(item, flag) ((item.fsManagerFlags & FS_MANAGER_##flag) != 0) - -#define FM_MANAGER_CHECK_ENABLED(item, flag) FS_MANAGER_FLAGS_ENABLED(item, check) -#define FM_MANAGER_WAIT_ENABLED(item, flag) FS_MANAGER_FLAGS_ENABLED(item, wait) - -struct FstabItem { - std::string deviceName; // Block device name - std::string mountPoint; // Mount point - std::string fsType; // File system type - std::string mountOptions; // File system mount options. readonly, rw, remount etc. - unsigned int fsManagerFlags; // flags defined by fs manager. -}; - -using Fstab = std::vector; -} // updater -#endif // __UPDATER_FS_MANAGER_H +/* + * 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 FLASHING_BLOCKDEVICE_H +#define FLASHING_BLOCKDEVICE_H +#include +#include +#include "flash_utils.h" + +namespace flashd { +enum class DeviceType { + DEVICE_UNKNOWN = 0, + DEVICE_SCSI = 1, + DEVICE_EMMC = 2, +}; + +class BlockDevice { +public: + BlockDevice(DeviceType type, const std::string &devPath) : devPath_(devPath), type_(type) {} + ~BlockDevice() {}; + + int Load(); + const std::string GetDeviceName(); + DeviceType GetDeviceType() + { + return type_; + } +private: + std::string ReadDeviceSysInfo(const std::string &type); + + std::string devPath_; + size_t devSize_ = 0; + size_t sectorSize_ = 0; // logical sector size + size_t physSectorSize_ = 0; // physical sector size + DeviceType type_ = DeviceType::DEVICE_UNKNOWN; +}; +using BlockDevicePtr = BlockDevice *; +} +#endif // FLASHING_BLOCKDEVICE_H \ No newline at end of file diff --git a/services/include/fs_manager/fstab_api.h b/services/flashd/common/flash_define.h old mode 100644 new mode 100755 similarity index 33% rename from services/include/fs_manager/fstab_api.h rename to services/flashd/common/flash_define.h index a8e36a2598dccc3cc4d84811a770492ead3e5f28..20361a07008c867b53f732674718022098684f8d --- a/services/include/fs_manager/fstab_api.h +++ b/services/flashd/common/flash_define.h @@ -1,10 +1,10 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 + * 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, @@ -12,17 +12,27 @@ * 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" -#ifndef __UPDATER_FS_MANAGER_FSTAB_API_H -#define __UPDATER_FS_MANAGER_FSTAB_API_H -#include -#include "fs_manager/fstab.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"; -namespace updater { -bool ReadFstabFromFile(const std::string &fstabFile, Fstab &fstabs); -struct FstabItem* FindFstabItemForPath(Fstab &fstab, const std::string &path); -struct FstabItem* FindFstabItemForMountPoint(Fstab &fstab, const std::string &mp); -unsigned long GetMountFlags(const std::string &mountOptions, std::string &fsSpecificOptions); -} // updater -#endif // __UPDATER_FS_MANAGER_FSTAB_API_ +// 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..d3e1d09b8b4e999c915e3c7a77cd651ee368a6f2 --- /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..cd4f3ffeaad5748700246ae3d0ef801177148358 --- /dev/null +++ b/services/flashd/daemon/daemon_unity.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_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 = 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 new file mode 100755 index 0000000000000000000000000000000000000000..2e84fe7547ed01099416bcb841f77d4a9692df39 --- /dev/null +++ b/services/flashd/daemon/daemon_updater.cpp @@ -0,0 +1,196 @@ +/* + * 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_updater.h" +#include "daemon_common.h" +#include "flashd/flashd.h" +#include "flash_utils.h" +#include "flash_define.h" + +namespace Hdc { +DaemonUpdater::DaemonUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_UPDATER_BEGIN; + commandData = CMD_UPDATER_DATA; +} + +DaemonUpdater::~DaemonUpdater() +{ + WRITE_LOG(LOG_DEBUG, "~DaemonUpdater refCount %d", refCount); +} + +bool DaemonUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ +#ifndef UPDATER_UT + if (!HdcTransferBase::CommandDispatch(command, payload, payloadSize)) { + return false; + } +#endif + if (flashHandle_ == nullptr) { + int ret = flashd::CreateFlashInstance(&flashHandle_, errorMsg_, + [&](uint32_t type, size_t dataLen, const void *context) { + SendProgress(dataLen); + }); + 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 {}; + SerialStruct::ParseFromString(pld, serialStrring); +#ifdef UPDATER_UT + pld.uncompressSize = pld.compressSize; +#endif + SendProgress(pld.uncompressSize); + break; + } + case CMD_UPDATER_CHECK: { + ProcessUpdateCheck(payload, payloadSize); + break; + } + case CMD_UPDATER_ERASE: { + std::string param(reinterpret_cast(payload), payloadSize); + RunUpdateShell(flashd::UPDATEMOD_ERASE, param, ""); + TaskFinish(); + break; + } + case CMD_UPDATER_FORMAT: { + std::string param(reinterpret_cast(payload), payloadSize); + RunUpdateShell(flashd::UPDATEMOD_FORMAT, param, ""); + TaskFinish(); + break; + } + default: + WRITE_LOG(LOG_FATAL, "CommandDispatch command %d", command); + return false; + } + return true; +}; + +void DaemonUpdater::ProcessUpdateCheck(const uint8_t *payload, const int payloadSize) +{ + uint64_t realSize = 0; + int ret = memcpy_s(&realSize, sizeof(realSize), payload, sizeof(realSize)); + 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; + ctxNow.fsOpenReq.data = &ctxNow; + ctxNow.transferBegin = Base::GetRuntimeMSec(); + ctxNow.fileSize = ctxNow.transferConfig.fileSize; + percentage_ = -1; + + WRITE_LOG(LOG_DEBUG, "ProcessUpdateCheck local function %s size %llu realSize %llu", + ctxNow.transferConfig.functionName.c_str(), ctxNow.fileSize, realSize); + uint8_t type = flashd::UPDATEMOD_FLASH; + if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) { + type = flashd::UPDATEMOD_UPDATE; + totalSize_ = static_cast(ctxNow.fileSize); + if (!MatchPackageExtendName(ctxNow.transferConfig.optionalName, ".bin")) { + totalSize_ += static_cast(realSize); // for decode from zip + } + totalSize_ += static_cast(realSize); // for verify + totalSize_ += static_cast(realSize); // for read to partition + totalSize_ += static_cast(realSize); // for write partition + } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) { + totalSize_ = static_cast(ctxNow.fileSize); + type = flashd::UPDATEMOD_FLASH; + } 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; + ret = flashd::DoUpdaterPrepare(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath); + 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); +#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); + AsyncUpdateFinish(type, ret, errorMsg_); +} + +void DaemonUpdater::SendProgress(size_t dataLen) +{ + currSize_ += dataLen; + 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_); + SendToAnother(CMD_UPDATER_PROGRESS, (uint8_t *)&percentage, sizeof(uint32_t)); + } +} + +void DaemonUpdater::WhenTransferFinish(CtxFile *context) +{ + uint64_t nMSec = Base::GetRuntimeMSec() - context->transferBegin; + double fRate = static_cast(context->indexIO) / nMSec; // / /1000 * 1000 = 0 + WRITE_LOG(LOG_DEBUG, "File for %s transfer finish Size:%lld time:%lldms rate:%.2lfkB/s", + ctxNow.transferConfig.functionName.c_str(), context->indexIO, nMSec, fRate); + + int ret = 0; + uint8_t type = flashd::UPDATEMOD_UPDATE; + if (ctxNow.transferConfig.functionName == CMDSTR_UPDATE_SYSTEM) { + type = flashd::UPDATEMOD_UPDATE; + ret = flashd::DoUpdaterFlash(flashHandle_, type, ctxNow.transferConfig.options, ctxNow.localPath); + } else if (ctxNow.transferConfig.functionName == CMDSTR_FLASH_PARTITION) { + type = flashd::UPDATEMOD_FLASH; + } + AsyncUpdateFinish(type, ret, errorMsg_); + TaskFinish(); +} + +void DaemonUpdater::AsyncUpdateFinish(uint8_t type, int32_t retCode, const string &result) +{ + 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 (retCode != 0) { + vecBuf.push_back(MSG_FAIL); + } else { + vecBuf.push_back(MSG_OK); + } + vecBuf.insert(vecBuf.end(), (uint8_t *)echo.c_str(), (uint8_t *)echo.c_str() + echo.size()); + SendToAnother(CMD_UPDATER_FINISH, vecBuf.data(), vecBuf.size()); +} + +#ifdef UPDATER_UT +void DaemonUpdater::DoTransferFinish() +{ + WhenTransferFinish(&ctxNow); +} +#endif +} // namespace Hdc \ No newline at end of file diff --git a/services/flashd/daemon/daemon_updater.h b/services/flashd/daemon/daemon_updater.h new file mode 100755 index 0000000000000000000000000000000000000000..6f7bb76f8ee027b05874600cd80e227ef1068bca --- /dev/null +++ b/services/flashd/daemon/daemon_updater.h @@ -0,0 +1,63 @@ +/* + * 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 HDC_DAEMON_UPDATER_H +#define HDC_DAEMON_UPDATER_H +#include + +#include "securec.h" +#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; +#ifdef UPDATER_UT + void DoTransferFinish(); +#endif +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 retCode, const string &result); + void SendProgress(size_t dataLen); +#ifdef UPDATER_UT + bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int size) + { + WRITE_LOG(LOG_DEBUG, "SendToAnother %d size %d", command, size); + return true; + } + void TaskFinish() + { + WRITE_LOG(LOG_DEBUG, "TaskFinish "); + return; + } +#endif +private: + double currSize_ = 0; + double totalSize_ = 0; + int32_t percentage_ = 0; + void* flashHandle_ = nullptr; + std::string errorMsg_ {}; +}; +} // namespace Hdc +#endif \ No newline at end of file diff --git a/services/flashd/daemon/flashd_main.cpp b/services/flashd/daemon/flashd_main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f5270bc28a0dab5f553e13f636aeda3c7b60c1e2 --- /dev/null +++ b/services/flashd/daemon/flashd_main.cpp @@ -0,0 +1,57 @@ +/* + * 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_common.h" +#include "daemon_updater.h" +#include "flashd/flashd.h" +#include "updater/updater.h" + +using namespace Hdc; +namespace flashd { +int flashd_main(int argc, char **argv) +{ + Base::SetLogLevel(LOG_LAST); // debug log print + 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")); + 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 || strncmp(modeSet, "tcp", 3) == 0) { // 3 tcp + enableTcp = true; + } else if (arg.find("-u") != std::string::npos) { + enableUsb = true; + } + } + + if (!enableTcp && !enableUsb) { + Base::PrintMessage("Both TCP and USB are disable, default enable usb"); + enableUsb = true; + } + HdcDaemon daemon(false); + daemon.InitMod(enableTcp, enableUsb); +#ifndef UPDATER_UT + daemon.WorkerPendding(); +#endif + return 0; +} +} diff --git a/services/flashd/flash_service.cpp b/services/flashd/flash_service.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c5050ba034746eafbf9b474dd8aa31f01b8e225f --- /dev/null +++ b/services/flashd/flash_service.cpp @@ -0,0 +1,645 @@ +/* + * 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_service.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blockdevice.h" +#include "fs_manager/mount.h" +#include "package/pkg_manager.h" +#include "securec.h" +#include "updater/updater.h" +#include "updater/updater_const.h" +#include "utils.h" + +using namespace hpackage; +using namespace updater; + +namespace flashd { +static std::atomic g_flashdRunning { false }; +FlashService::~FlashService() +{ + for (auto part : partitions_) { + printf("LoadBlockDevice %s \n", part->GetPartitionName().c_str()); + delete part; + } + partitions_.clear(); + for (auto dev : blockDevices_) { + delete dev; + } + blockDevices_.clear(); +} + +int FlashService::LoadSysDevice() +{ + if (loadSysDevice_) { + return 0; + } + return LoadBlockDevice("/dev/block"); +} + +int FlashService::DoUpdate(const std::string &packageName) +{ + int ret = 0; + FLASHING_LOGI("DoUpdate packageName %s", packageName.c_str()); + FLASHING_CHECK(access(packageName.c_str(), 0) == 0, + return FLASHING_IMAGE_INVALID, "Invalid package %s for update", packageName.c_str()); + ret = updater::IsSpaceCapacitySufficient(packageName); + if (ret == UPDATE_SPACE_NOTENOUGH) { + RecordMsg(updater::ERROR, "Free space is not enough"); + return FLASHING_SPACE_NOTENOUGH; + } + FLASHING_LOGI("Check space for packageName %s success", packageName.c_str()); + + uint64_t pkgLen = 0; + PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); + FLASHING_CHECK(pkgManager != nullptr, return FLASHING_PACKAGE_INVALID, "Failed to GetPackageInstance"); + pkgManager->SetPkgDecodeProgress([&](int type, size_t writeDataLen, const void *context) { + pkgLen += writeDataLen; + PostProgress(UPDATEMOD_UPDATE, writeDataLen, context); + }); + std::vector components; + ret = pkgManager->LoadPackage(packageName, utils::GetCertName(), components); + 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()); + + 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) { + size_t dataLen = std::stoll(content); + PostProgress(UPDATEMOD_UPDATE, dataLen, nullptr); + } + }); +#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; +} + +int FlashService::DoFlashPartition(const std::string &fileName, const std::string &partition) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoFlashPartition partition %s image:%s", partition.c_str(), fileName.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoFlash(fileName); +} + +int FlashService::GetPartitionPath(const std::string &partition, std::string ¶titionPath) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FLASH, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to flash partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to flash partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoFlashPartition partition %s", partition.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + paratitionPath = part->GetPartitionPath(); + return 0; +} + +int FlashService::DoErasePartition(const std::string &partition) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_ERASE, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to erase partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to erase partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + FLASHING_LOGI("DoErasePartition partition %s ", partition.c_str()); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoErase(); +} + +int FlashService::DoFormatPartition(const std::string &partition, const std::string &fsType) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_FORMAT, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to format partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to format partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + if (part->IsOnlyErase()) { + FLASHING_LOGI("DoFormatPartition format partition %s", partition.c_str()); + return part->DoErase(); + } + FLASHING_LOGI("DoFormatPartition partition %s fsType:%s", partition.c_str(), fsType.c_str()); + return part->DoFormat(fsType); +} + +int FlashService::DoResizeParatiton(const std::string &partition, uint32_t blocks) +{ + int ret = CheckOperationPermission(flashd::UPDATEMOD_UPDATE, partition); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Forbit to resize partition %s", partition.c_str()); + return FLASHING_NOPERMISSION, "Forbit to resize partition %s", partition.c_str()); + + ret = LoadSysDevice(); + FLASHING_CHECK(ret == 0, + RecordMsg(updater::ERROR, "Can not read device information"); + return FLASHING_PART_NOEXIST, "Failed to load partition"); + + PartitionPtr part = GetPartition(partition); + FLASHING_CHECK(part != nullptr, + RecordMsg(updater::ERROR, "Can not find partition %s", partition.c_str()); + return FLASHING_PART_NOEXIST, "Failed to get partition %s", partition.c_str()); + return part->DoResize(blocks); +} + +PartitionPtr FlashService::GetPartition(const std::string &partition) const +{ + const std::string partName = GetPartNameByAlias(partition); + for (auto part : partitions_) { + if (strcmp(partName.c_str(), part->GetPartitionName().c_str()) == 0) { + return part; + } + } + return nullptr; +} + +int FlashService::LoadBlockDevice(const std::string &fileDir) +{ + std::vector partitionsName {}; + struct stat dirStat = {}; + int ret = stat(fileDir.c_str(), &dirStat); + FLASHING_CHECK(ret != -1 && S_ISDIR(dirStat.st_mode), return -1, "Invlid dir %s", fileDir.c_str()); + + std::vector buffer(DEVICE_PATH_SIZE, 0); + struct dirent *entry = nullptr; + DIR *dir = opendir(fileDir.c_str()); + while ((entry = readdir(dir)) != nullptr) { + if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) { + continue; + } + std::string devPath = fileDir + "/" + entry->d_name; + 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); + } + ret = stat(devPath.c_str(), &dirStat); + FLASHING_CHECK(ret != -1, break, "Invlid dir %s %s", devPath.c_str(), strerror(errno)); + uint32_t devMajor = major(dirStat.st_rdev); + uint32_t devMinor = minor(dirStat.st_rdev); + if (devMajor == LOOP_MAJOR) { + continue; + } + ret = 0; + if (SCSI_BLK_MAJOR(devMajor)) { + 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) { // 0x08 emmc + ret = AddNewBlockDevice(DeviceType::DEVICE_EMMC, devPath); + } else { + partitionsName.push_back(devPath); + } + } + FLASHING_CHECK(ret == 0, break, "Failed to add device %s", devPath.c_str()); + } + closedir(dir); + FLASHING_CHECK(ret == 0, return -1, "Failed to add device %s", fileDir.c_str()); + ret = LoadPartition(partitionsName); + loadSysDevice_ = true; + return ret; +} + +int FlashService::LoadPartition(std::vector &partitionsNames) +{ + std::sort(std::begin(partitionsNames), std::end(partitionsNames), std::less()); + for (auto device : blockDevices_) { + for (std::string path : partitionsNames) { + std::string name = GetBaseName(path); + if (strncmp(name.c_str(), device->GetDeviceName().c_str(), device->GetDeviceName().size()) != 0) { + continue; + } + AddNewPartition(path, device); + } + } + return 0; +} + +int FlashService::AddNewPartition(const std::string &path, BlockDevicePtr device) +{ + std::string name = GetBaseName(path); + PartitionPtr part = new Partition(name, GetRealPath(path), device, this); + FLASHING_CHECK(part != nullptr, return -1, "Failed to create partition %s", path.c_str()); + int ret = part->Load(); + FLASHING_CHECK(ret == 0, delete part; + return -1, "Failed to create partition %s", path.c_str()); + partitions_.push_back(part); + return 0; +} + +int FlashService::AddNewBlockDevice(DeviceType type, const std::string &devPath) +{ + BlockDevicePtr device = new BlockDevice(type, GetRealPath(devPath)); + FLASHING_CHECK(device != nullptr, return -1, "Failed to create device %s", devPath.c_str()); + int ret = device->Load(); + FLASHING_CHECK(ret == 0, delete device; + return 0, "Failed to create device %s", devPath.c_str()); + blockDevices_.push_back(device); + return 0; +} + +std::string FlashService::ReadSysInfo(const std::string &path, const std::string &type, std::vector &table) +{ + std::string returnStr; + auto file = std::unique_ptr(fopen(path.c_str(), "r"), fclose); + FLASHING_CHECK(file != nullptr, return "", "Failed to open %s", path.c_str()); + std::vector buffer(LINE_BUFFER_SIZE, 0); + while (fgets(buffer.data(), LINE_BUFFER_SIZE, file.get()) != nullptr) { + if (type == "uevent") { + table.push_back(buffer.data()); + } else if (type == "start") { + returnStr = std::string(buffer.data()); + break; + } else if (type == "size") { + returnStr = std::string(buffer.data()); + break; + } else if (type == "partition") { + returnStr = std::string(buffer.data()); + break; + } + memset_s(buffer.data(), LINE_BUFFER_SIZE, 0, LINE_BUFFER_SIZE); + } + return returnStr; +} + +std::string FlashService::GetParamFromTable(const std::vector &table, const std::string ¶m) +{ + for (std::string line : table) { + std::string::size_type pos = line.find(param); + if (pos != std::string::npos) { + return line.substr(param.size(), line.size() - 1 - param.size()); + } + } + return ""; +} + +int FlashService::ExecCommand(const std::vector &cmds) +{ + std::vector extractedCmds; + for (const auto &cmd : cmds) { + extractedCmds.push_back(const_cast(cmd.c_str())); + } + extractedCmds.push_back(nullptr); + pid_t pid = fork(); + 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; +} + +void FlashService::RecordMsg(uint8_t level, const char *msg, ...) +{ + errorLevel_ = level; + va_list vaArgs; + va_start(vaArgs, msg); + std::vector zc(MAX_SIZE_BUF); + const int retSize = vsnprintf_s(zc.data(), MAX_SIZE_BUF, zc.size() - 1, msg, vaArgs); + if (retSize >= 0) { + errorMsg_ = std::string(zc.data(), retSize); + } + va_end(vaArgs); +} + +void FlashService::PostProgress(uint32_t type, size_t dataLen, const void *context) const +{ + if (progressor_ != nullptr) { + progressor_(type, dataLen, context); + } +} + +int FlashService::CheckOperationPermission(int type, const std::string &partition) const +{ + FLASHING_CHECK(type < UPDATEMOD_MAX, return 1, "Invalid type %d", type); + std::vector forbitPartName[] = { + {}, // updater + {"updater"}, // flash + {"updater", "boot", "kernel"}, // erase + {"updater", "boot", "kernel"} // format + }; + if (forbitPartName[type].size() == 0) { + return 0; + } + const std::string partName = GetPartNameByAlias(partition); + auto it = std::find (forbitPartName[type].begin(), forbitPartName[type].end(), partName); + return it != forbitPartName[type].end(); +} + +const std::string FlashService::GetBaseName(const std::string &path) +{ + std::string::size_type pos = path.find_last_of('/') + 1; + return path.substr(pos, path.size() - pos); +} + +const std::string FlashService::GetPathRoot(const std::string &path) +{ + std::string::size_type pos = path.find_first_of('/', 1); + return path.substr(0, pos); +} + +const std::string FlashService::GetPartNameByAlias(const std::string &alias) +{ + std::map> partNameMap = { + { "userdata", { "data", "/data", "userdata" } }, + { "system", { "system", "/system" } }, + { "vendor", { "vendor", "/vendor" } }, + { "misc", { "misc", "/misc" } }, + { "updater", { "updater", "/updater" } }, + { "kernel", { "boot" } }, // image + { "boot", { "fastboot" } }, // fastboot + }; + for (auto iter = partNameMap.begin(); iter != partNameMap.end(); iter++) { + for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); iter2++) { + if (strcmp(alias.c_str(), (*iter2).c_str()) == 0) { + return iter->first; + } + } + } + return alias; +} + +const std::string FlashService::GetRealPath(const std::string &path) +{ + std::vector realPath(DEVICE_PATH_SIZE, 0); + return realpath(path.c_str(), realPath.data()); +} + +bool FlashService::CheckFreeSpace(const std::string &root, uint32_t blocks) +{ + struct statvfs64 vfs {}; + int ret = statvfs64(root.c_str(), &vfs); + FLASHING_CHECK(ret >= 0, return false, "Failed to statvfs %s", root.c_str()); + if (static_cast(vfs.f_bsize) == DEFAULT_BLOCK_SIZE) { + return static_cast(vfs.f_bfree) < static_cast(blocks); + } + return static_cast(vfs.f_bfree) < (blocks / static_cast(vfs.f_bsize)) * DEFAULT_BLOCK_SIZE; +} + +static std::string GetValueFromParam(const std::vector ¶ms, + const std::string ¶mType, const std::string &defValue) +{ + std::string ret = defValue; + for (size_t i = 0; i < params.size(); i++) { + if (strcmp(paramType.c_str(), params[i].c_str()) == 0) { + if (i < (params.size() - 1)) { + ret = params[i + 1]; + } else { + ret = "true"; + } + } + } + return ret; +} + +static bool FilterParam(const std::string ¶m, const std::vector &filter) +{ + auto iter = filter.begin(); + while (iter != filter.end()) { + if (strcmp(param.c_str(), (*iter).c_str()) == 0) { + return true; + } + iter++; + } + return false; +} + +static int GetCmdParam(uint8_t type, const std::string &origString, + const std::vector &filter, std::vector &resultStrings) +{ + static uint32_t paramMinNumber[flashd::UPDATEMOD_MAX + 1] = { 1, 2, 2, 2, 0 }; + std::string::size_type p1 = 0; + std::string::size_type p2 = origString.find(" "); + + while (p2 != std::string::npos) { + if (p2 == p1) { + ++p1; + p2 = origString.find(" ", p1); + continue; + } + + std::string param = origString.substr(p1, p2 - p1); + if (!FilterParam(param, filter)) { + resultStrings.push_back(param); + } + p1 = p2 + 1; + p2 = origString.find(" ", p1); + } + + if (p1 != origString.size()) { + std::string param = origString.substr(p1); + if (!FilterParam(param, filter)) { + resultStrings.push_back(param); + } + } + FLASHING_CHECK((resultStrings.size() >= paramMinNumber[type]) && (type <= flashd::UPDATEMOD_MAX), + return FLASHING_ARG_INVALID, "Invalid param for %d cmd %s", type, origString.c_str()); + return 0; +} + +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); + 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; +} + +int DoUpdaterPrepare(FlashHandle handle, uint8_t type, const std::string &cmdParam, std::string &filePath) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + flashd::FlashService *flash = static_cast(handle); + + std::vector params {}; + int ret = GetCmdParam(type, cmdParam, { "-f" }, params); + FLASHING_CHECK(ret == 0, flash->RecordMsg(updater::ERROR, "Invalid param for %d", type); + return FLASHING_ARG_INVALID, "Invalid param for %d", type); + FLASHING_DEBUG("DoUpdaterPrepare type: %d param %s filePath %s", type, cmdParam.c_str(), filePath.c_str()); + switch (type) { + case flashd::UPDATEMOD_UPDATE: { + filePath = FLASHD_FILE_PATH + filePath; + // 检查剩余分区大小,扩展分区 + const std::string root = flashd::FlashService::GetPathRoot(FLASHD_FILE_PATH); + ret = MountForPath(root); + 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, 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); + } + break; + } + case flashd::UPDATEMOD_FLASH: { + ret = flash->GetPartitionPath(params[0], filePath); + break; + } + default: + ret = flashd::FLASHING_SYSTEM_ERROR; + break; + } + return ret; +} + +int DoUpdaterFlash(FlashHandle handle, uint8_t type, const std::string &cmdParam, const std::string &filePath) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + flashd::FlashService *flash = static_cast(handle); + + std::vector params {}; + int ret = GetCmdParam(type, cmdParam, {"-f"}, params); + 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); + break; + } + case flashd::UPDATEMOD_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, g_flashdRunning = false; + return FLASHING_ARG_INVALID, "Invalid param size for format"); + ret = flash->DoFormatPartition(params[1], fsType); + break; + } + default: + ret = flashd::FLASHING_SYSTEM_ERROR; + break; + } + return ret; +} + +int DoUpdaterFinish(FlashHandle handle, uint8_t type, const std::string &partition) +{ + FLASHING_CHECK(handle != nullptr, return FLASHING_ARG_INVALID, "Invalid handle for %d", type); + FLASHING_DEBUG("DoUpdaterFinish type: %d %s", type, partition.c_str()); + 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/flash_service.h b/services/flashd/flash_service.h new file mode 100755 index 0000000000000000000000000000000000000000..e9420784426b2d715853cbfe7191605b3a830ad1 --- /dev/null +++ b/services/flashd/flash_service.h @@ -0,0 +1,77 @@ +/* + * 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 FLASHING_H +#define FLASHING_H +#include +#include +#include +#include +#include "blockdevice.h" +#include "partition.h" +#include "updater/updater.h" + +// Just update-mode use +namespace flashd { +class FlashService { +public: + FlashService(std::string &errorMsg, ProgressFunction progressor) + : errorMsg_(errorMsg), progressor_(progressor) {} + explicit FlashService(std::string &errorMsg) : errorMsg_(errorMsg), progressor_(nullptr) {} + ~FlashService(); + + int DoUpdate(const std::string &packageName); + int DoFlashPartition(const std::string &fileName, const std::string &partition); + int DoErasePartition(const std::string &partition); + int DoFormatPartition(const std::string &partition, const std::string &fsType); + int GetPartitionPath(const std::string &partition, std::string ¶titionPath); + int DoResizeParatiton(const std::string &partition, uint32_t blocks); + + int LoadSysDevice(); + PartitionPtr GetPartition(const std::string &partition) const; + + void PostProgress(uint32_t type, size_t dataLen, const void *context) const; + void RecordMsg(uint8_t level, const char *msg, ...); + uint8_t GetErrorLevel() const + { + return errorLevel_; + } + + static std::string ReadSysInfo(const std::string &path, const std::string &type, std::vector &table); + static std::string GetParamFromTable(const std::vector &table, const std::string ¶m); + static int ExecCommand(const std::vector &cmds); + + static const std::string GetBaseName(const std::string &path); + static const std::string GetPathRoot(const std::string &path); + static const std::string GetRealPath(const std::string &path); + static const std::string GetPartNameByAlias(const std::string &alias); + static bool CheckFreeSpace(const std::string &root, uint32_t blocks); +private: + int LoadBlockDevice(const std::string &fileDir); + int LoadPartition(std::vector &partitionsNames); + + int AddNewBlockDevice(DeviceType type, const std::string &devPath); + int AddNewPartition(const std::string &path, BlockDevicePtr device); + + int CheckOperationPermission(int type, const std::string &partition) const; + std::string &errorMsg_; + ProgressFunction progressor_; + uint8_t errorLevel_ = 0; + bool loadSysDevice_ = false; + std::vector blockDevices_; + std::vector partitions_; +}; +} +#endif // FLASHING_H \ No newline at end of file diff --git a/services/flashd/flash_utils.h b/services/flashd/flash_utils.h new file mode 100755 index 0000000000000000000000000000000000000000..0f6a415dc9aef5de824b7c08197e3d24a11d6ca7 --- /dev/null +++ b/services/flashd/flash_utils.h @@ -0,0 +1,49 @@ +/* + * 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 FLASHING_UTILS_H +#define FLASHING_UTILS_H +#include + +#include "flashd/flashd.h" +#include "log/log.h" +#include "securec.h" + +namespace flashd { +#define FLASHING_LOGE(format, ...) Logger(updater::ERROR, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_DEBUG(format, ...) Logger(updater::DEBUG, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_LOGI(format, ...) Logger(updater::INFO, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) +#define FLASHING_LOGW(format, ...) Logger(updater::WARNING, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__) + +#define FLASHING_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + FLASHING_LOGE(__VA_ARGS__); \ + exper; \ + } + +static constexpr size_t BUFFER_SIZE = 64 * 1024; +static constexpr uint32_t LOOP_MAJOR = 7; +static constexpr uint32_t SCSI_CDROM_MAJOR = 11; +static constexpr uint32_t SCSI_DISK0_MAJOR = 8; +static constexpr uint32_t SDMMC_MAJOR = 179; +static constexpr uint32_t DEVICE_PATH_SIZE = 256; +static constexpr uint32_t LINE_BUFFER_SIZE = 256; +static constexpr size_t SECTOR_SIZE_DEFAULT = 512; +#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR) + +class FlashService; +using FlashingPtr = FlashService *; +} // namespace flashd +#endif // FLASHING_UTILS_H 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 new file mode 100755 index 0000000000000000000000000000000000000000..0b4cd69b896e0ef082c5305362805886a3dd2262 --- /dev/null +++ b/services/flashd/host/host_updater.cpp @@ -0,0 +1,354 @@ +/* + * 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 "host_updater.h" + +#include +#include "common.h" +#include "flash_define.h" +#include "transfer.h" +#include "serial_struct.h" + +namespace { +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); +} +namespace Hdc { +HostUpdater::HostUpdater(HTaskInfo hTaskInfo) : HdcTransferBase(hTaskInfo) +{ + commandBegin = CMD_UPDATER_BEGIN; + commandData = CMD_UPDATER_DATA; +} + +HostUpdater::~HostUpdater() {} + +void HostUpdater::RunQueue(CtxFile &context) +{ + refCount++; + context.localPath = context.taskQueue.back(); + uv_fs_open(loopTask, &context.fsOpenReq, context.localPath.c_str(), O_RDONLY, 0, OnFileOpen); + context.master = true; +} + +bool HostUpdater::BeginTransfer(CtxFile &context, + const std::string &function, const char *payload, int minParam, int fileIndex) +{ + int argc = 0; + char **argv = Base::SplitCommandToArgs(payload, &argc); + HOSTUPDATER_CHECK(!(argv == nullptr || argc < minParam || fileIndex >= argc), delete[]((char *)argv); + return false, "Invalid param for cmd \"%s\"", function.c_str()); + + int maxParam = minParam; + bool force = strstr(payload, "-f") != nullptr; + if (force) { + maxParam += 1; + } + 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 (force && (fileIndex + 1 < argc) && strcmp(argv[fileIndex + 1], "-f") != 0) { + context.localPath = argv[fileIndex + 1]; + } else { + context.localPath = argv[fileIndex]; + } + + if (MatchPackageExtendName(context.localPath, ".img")) { + 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 { + 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); + 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; +} + +std::string HostUpdater::GetFileName(const std::string &fileName) const +{ + int32_t pos = fileName.find_last_of('/'); + if (pos < 0) { // win32 + pos = fileName.find_last_of('\\'); + } + return fileName.substr(pos + 1, fileName.size()); +} + +void HostUpdater::CheckMaster(CtxFile *context) +{ + uv_fs_t fs; + Base::ZeroStruct(fs.statbuf); + uv_fs_fstat(nullptr, &fs, context->fsOpenReq.result, nullptr); + context->transferConfig.fileSize = fs.statbuf.st_size; + uv_fs_req_cleanup(&fs); + + WRITE_LOG(LOG_DEBUG, "CheckMaster %s %llu", context->transferConfig.functionName.c_str(), fs.statbuf.st_size); + context->transferConfig.optionalName = GetFileName(context->localPath); + std::string bufString = SerialStruct::SerializeToString(context->transferConfig); + + const uint64_t verdorSize = static_cast(1024 * 1024) * 256; + const uint64_t systemSize = static_cast(1024 * 1024) * 1500; + const uint64_t minSize = static_cast(1024 * 1024) * 10; + uint64_t realSize = verdorSize; + if (fs.statbuf.st_size > minSize) { + realSize += systemSize; + } + std::vector buffer(sizeof(realSize) + bufString.size()); + int ret = memcpy_s(buffer.data(), buffer.size(), &realSize, sizeof(realSize)); + int ret2 = memcpy_s(buffer.data() + sizeof(realSize), buffer.size(), bufString.c_str(), bufString.size()); + if ((ret == 0) && (ret2 == 0)) { + SendToAnother(CMD_UPDATER_CHECK, (uint8_t *)buffer.data(), buffer.size()); + } +} + +bool HostUpdater::CheckCmd(const std::string &function, const char *payload, int param) +{ + int argc = 0; + char **argv = Base::SplitCommandToArgs(payload, &argc); + HOSTUPDATER_CHECK(argv != nullptr, return false, "Can not parser cmd \"%s\"", function.c_str()); + delete[]((char *)argv); + 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) { + maxParam += 1; + } + if (strstr(payload, "-t") != nullptr) { + maxParam += 1; + maxParam += 1; + } + HOSTUPDATER_CHECK(argc == maxParam, return false, + "Invalid param for cmd \"%s\" %d %d", function.c_str(), argc, maxParam); + return true; +} + +bool HostUpdater::CommandDispatch(const uint16_t command, uint8_t *payload, const int payloadSize) +{ + 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%%"); + sendProgress = true; + SendRawData(reinterpret_cast(s.data()), s.size()); + break; + } + case CMD_UPDATER_UPDATE_INIT: + ret = BeginTransfer(ctxNow, CMDSTR_UPDATE_SYSTEM, reinterpret_cast(payload), 1, 0); + break; + case CMD_UPDATER_FLASH_INIT: + ret = BeginTransfer(ctxNow, CMDSTR_FLASH_PARTITION, + reinterpret_cast(payload), 2, 1); // 2 cmd min param for flash + break; + case CMD_UPDATER_FINISH: + ret = CheckUpdateContinue(command, payload, payloadSize); + break; + case CMD_UPDATER_ERASE: { + if (!CheckCmd(CMDSTR_ERASE_PARTITION, reinterpret_cast(payload), cmdFroErase)) { + return false; + } + SendToAnother(CMD_UPDATER_ERASE, payload, payloadSize); + ctxNow.taskQueue.push_back(reinterpret_cast(payload)); + break; + } + case CMD_UPDATER_FORMAT: { + if (!CheckCmd(CMDSTR_FORMAT_PARTITION, reinterpret_cast(payload), cmdFroFormat)) { + return false; + } + SendToAnother(CMD_UPDATER_FORMAT, payload, payloadSize); + ctxNow.taskQueue.push_back(reinterpret_cast(payload)); + break; + } + case CMD_UPDATER_PROGRESS: + if (payloadSize >= (int)sizeof(uint32_t)) { + ProcessProgress(*(uint32_t *)payload); + } + break; + default: + break; + } + return ret; +} + +void HostUpdater::ProcessProgress(uint32_t percentage) +{ + if (!sendProgress) { + return; + } + 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; + std::vector buffer(bufferSize); + if (percentage == PERCENT_CLEAR) { // clear + SendRawData(reinterpret_cast(backStr.data()), backStr.size()); + SendRawData(reinterpret_cast(breakStr.data()), breakStr.size()); + 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()); + sendProgress = false; + } +} + +bool HostUpdater::CheckUpdateContinue(const uint16_t command, const uint8_t *payload, int payloadSize) +{ + 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) && 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 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 new file mode 100755 index 0000000000000000000000000000000000000000..f11a5d039f0c171af6bc6010e006f111688e194b --- /dev/null +++ b/services/flashd/host/host_updater.h @@ -0,0 +1,68 @@ +/* + * 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 HDC_HOST_UPDATER_H +#define HDC_HOST_UPDATER_H +#include "common.h" +#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, ...) + { + return; + } + bool SendToAnother(const uint16_t command, uint8_t *bufPtr, const int 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 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..a28bba7dcde20e99a2bf935dd2612f4e72b0834c --- /dev/null +++ b/services/flashd/host/main.cpp @@ -0,0 +1,296 @@ +/* + * 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 + (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 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::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..da4d8a1d92ec63de2505a2524e9df7d40398b57e --- /dev/null +++ b/services/flashd/host/server.cpp @@ -0,0 +1,797 @@ +/* + * 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() +{ + uv_rwlock_rdlock(&daemonAdmin); + for (auto 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..2cbf92289781052054639bad59aa69e17c0b55e9 --- /dev/null +++ b/services/flashd/host/server_for_client.cpp @@ -0,0 +1,674 @@ +/* + * 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); // 2 len + 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..a300c7454d70a851e2d5ed127e68c43c84053096 --- /dev/null +++ b/services/flashd/host/translate.cpp @@ -0,0 +1,249 @@ +/* + * 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 (!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 new file mode 100755 index 0000000000000000000000000000000000000000..aa4264f08f0ee4711600a006c11a2084bc322227 --- /dev/null +++ b/services/flashd/partition.cpp @@ -0,0 +1,412 @@ +/* + * 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 "partition.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash_service.h" +#include "utils.h" + +namespace flashd { +Partition::~Partition() +{ + if (fd_ != -1) { + close(fd_); + } +} + +int Partition::Load() +{ + std::vector table; + std::string info = ReadPartitionSysInfo(devName_, "partition", table); + FLASHING_CHECK(!info.empty(), return -1, "Can not get partition for %s", devName_.c_str()); + partNumber_ = atoi(info.c_str()); + + ReadPartitionSysInfo(devName_, "uevent", table); + info = FlashService::GetParamFromTable(table, "DEVNAME="); + FLASHING_CHECK(info == devName_, return -1, "Failed to check dev name %s %s", info.c_str(), devName_.c_str()); + + partName_ = FlashService::GetParamFromTable(table, "PARTNAME="); + if (partName_.empty()) { + partName_ = devName_; + } + int ret = Partition::GetMountInfo(); + FLASHING_LOGI("Partition info devName \"%s\" partPath_ \"%s\" partName_ \"%s\"", + devName_.c_str(), partPath_.c_str(), partName_.c_str()); + if (!mountPoint_.empty()) { + FLASHING_LOGI("Partition mount info mount \"%s\" fs %s flags: %s", + mountPoint_.c_str(), fsType_.c_str(), mountFlags_.c_str()); + } + return ret; +} + +int Partition::DoFlash(const std::string &fileName) +{ + int ret = Open(); + FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for flash", partName_.c_str()); + + auto inputFd = open(fileName.c_str(), O_RDONLY); + FLASHING_CHECK(inputFd > 0, + flash_->RecordMsg(updater::ERROR, "Can not open image \"%s\" error: %s", fileName.c_str(), strerror(errno)); + return FLASHING_NOPERMISSION, "Can not open image \"%s\" error: %s", fileName.c_str(), strerror(errno)); + + struct stat st {}; + size_t fileSize = 1; + if (fstat(inputFd, &st) >= 0) { + fileSize = st.st_size; + } + + std::vector content(BUFFER_SIZE); + ssize_t readLen = read(inputFd, content.data(), content.size()); + FLASHING_CHECK(readLen >= 0, close(inputFd); + return FLASHING_PART_WRITE_ERROR, "Failed to flash data of len %d", readLen); + ret = WriteRowData(inputFd, fileSize, content, readLen); + close(inputFd); + FLASHING_CHECK(ret == 0, return ret, "Failed to write %s", fileName.c_str()); + FLASHING_LOGI("DoFlash partition %s image:%s success", partPath_.c_str(), fileName.c_str()); + return ret; +} + +int Partition::DoErase() +{ + int ret = Open(); + FLASHING_CHECK(ret == 0, return ret, "Can not open partiton %s for erase", partName_.c_str()); + + if (!IsBlockDevice(fd_)) { + return 0; + } + + uint64_t size = GetBlockDeviceSize(fd_); + FLASHING_LOGI("DoErase partition %s size %luM", partPath_.c_str(), size); + uint64_t range[2] = {0}; + range[1] = size; + ret = ioctl(fd_, BLKSECDISCARD, &range); + FLASHING_LOGI("DoErase partition %s ret %d", partPath_.c_str(), ret); + 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_); + } + FLASHING_LOGI("DoErase partition %s erase success", partPath_.c_str()); + return 0; +} + +int Partition::DoFormat(const std::string &fsType) +{ + 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); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to get param"); + ret = FlashService::ExecCommand(formatCmds); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to format \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to format \"%s\" error: %s", partPath_.c_str(), strerror(ret)); + + fsType_ = fsType; + ret = DoMount(); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to mount \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to mount \"%s\"", partPath_.c_str()); + FLASHING_LOGI("DoFormat partition %s format %s success", partName_.c_str(), fsType_.c_str()); + return ret; +} + +int Partition::DoResize(uint32_t blocks) +{ + int ret = 0; + bool needResize = false; + if (!mountPoint_.empty()) { + needResize = FlashService::CheckFreeSpace(mountPoint_, blocks); + } + if (!needResize) { + FLASHING_LOGI("No need to resize partition %s", partName_.c_str()); + return 0; + } + ret = DoUmount(); + FLASHING_CHECK(ret == 0, return FLASHING_PART_WRITE_ERROR, "Failed to umount partition"); + + std::vector formatCmds; + formatCmds.push_back(RESIZE_TOOL); + formatCmds.push_back(partPath_); + ret = FlashService::ExecCommand(formatCmds); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to resize \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to resize \"%s\" error: %s", partName_.c_str(), strerror(ret)); + ret = DoMount(); + FLASHING_CHECK(ret == 0, + flash_->RecordMsg(updater::ERROR, "Failed to mount \"%s\" error: %s", partName_.c_str(), strerror(ret)); + return FLASHING_PART_WRITE_ERROR, "Failed to mount \"%s\"", partPath_.c_str()); + FLASHING_LOGI("Resize partition %s success", partName_.c_str()); + return 0; +} + +int Partition::Open() +{ + if (fd_ <= 0) { + 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)); + return FLASHING_NOPERMISSION, + "Can open partition %s error %s", partPath_.c_str(), strerror(errno)); + return 0; +} + +int Partition::WriteRowData(int inputFd, size_t fileSize, std::vector &buffer, size_t dataSize) +{ + size_t dataLen = dataSize; + size_t totalWrite = 0; + do { +#ifndef UPDATER_UT + ssize_t writeLen = write(fd_, buffer.data(), dataLen); +#else + ssize_t writeLen = dataLen; +#endif + FLASHING_CHECK(writeLen >= 0, + return FLASHING_PART_WRITE_ERROR, "Failed to write data of len %d", dataLen); + totalWrite += writeLen; + + // continue read and write + 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_); + return 0; +} + +int Partition::IsBlockDevice(int fd) const +{ + struct stat st {}; + int ret = fstat(fd, &st); + FLASHING_CHECK(ret >= 0, return 0, "Invalid get fstate %d", errno); + return S_ISBLK(st.st_mode); +} + +uint64_t Partition::GetBlockDeviceSize(int fd) const +{ + uint64_t size = 0; + int ret = ioctl(fd, BLKGETSIZE64, &size); + return (ret == 0) ? size : 0; +} + +std::string Partition::ReadPartitionSysInfo(const std::string &partition, + const std::string &type, std::vector &table) +{ + std::vector buffer(DEVICE_PATH_SIZE, 0); + int ret = snprintf_s(buffer.data(), DEVICE_PATH_SIZE, DEVICE_PATH_SIZE - 1, + "/sys/block/%s/%s/%s", device_->GetDeviceName().c_str(), partition.c_str(), type.c_str()); + FLASHING_CHECK(ret != -1, return "", "Failed to snprintf_s %s", device_->GetDeviceName().c_str()); + return FlashService::ReadSysInfo(buffer.data(), type, table); +} + +const std::string Partition::GetPartitionName() const +{ + return partName_; +} + +int Partition::GetMountInfo() +{ + auto file = std::unique_ptr(fopen("/proc/mounts", "r"), fclose); + FLASHING_CHECK(file != nullptr, return -1, "Failed to open mounts "); + std::vector buffer(LINE_BUFFER_SIZE, 0); + std::vector mount(DEVICE_PATH_SIZE, 0); + std::vector fsType(DEVICE_PATH_SIZE, 0); + std::vector dev(DEVICE_PATH_SIZE, 0); + std::vector flags(DEVICE_PATH_SIZE, 0); + while (fgets(buffer.data(), LINE_BUFFER_SIZE, file.get()) != nullptr) { + // clang-format off + int ret = sscanf_s(buffer.data(), "%255s %255s %255s %255s %*d %*d\n", + dev.data(), DEVICE_PATH_SIZE - 1, + mount.data(), DEVICE_PATH_SIZE - 1, + fsType.data(), DEVICE_PATH_SIZE - 1, + flags.data(), DEVICE_PATH_SIZE - 1); + // clang-format on + if (ret <= 0) { + break; + } + struct stat st {}; + if (lstat(dev.data(), &st) < 0) { + continue; + } + if (S_ISLNK(st.st_mode)) { + readlink(dev.data(), dev.data(), DEVICE_PATH_SIZE); + } + if (strncmp(dev.data(), partPath_.c_str(), partPath_.size()) == 0 || + (partName_ == "system" && strncmp(mount.data(), "/", strlen("/")) == 0)) { + mountPoint_.assign(mount.data()); + fsType_.assign(fsType.data()); + mountFlags_.assign(flags.data()); + break; + } + memset_s(buffer.data(), LINE_BUFFER_SIZE, 0, LINE_BUFFER_SIZE); + } + return 0; +} + +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)); +#endif + return 0; +} + +int Partition::DoMount() +{ + if (mountPoint_.empty()) { + return 0; + } + struct stat st {}; + int ret = lstat(mountPoint_.c_str(), &st); + FLASHING_CHECK(ret >= 0, return ret, "Failed to fstat %s error %s", mountPoint_.c_str(), strerror(errno)); + + if (S_ISLNK(st.st_mode)) { + unlink(mountPoint_.c_str()); + } + mkdir(mountPoint_.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + // get mount flags + 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 { + break; + } + } + return ret; +} + +int Partition::BuildCommandParam(const std::string &fsType, std::vector &formatCmds) const +{ + std::map fsToolsMap = { + { "ext4", FORMAT_TOOL_FOR_EXT4 }, + { "f2fs", FORMAT_TOOL_FOR_F2FS }, + }; + auto it = fsToolsMap.find(fsType); + FLASHING_CHECK(it != fsToolsMap.end(), + flash_->RecordMsg(updater::ERROR, "Not support fs type %s", fsType.c_str()); + return FLASHING_FSTYPE_NOT_SUPPORT, "Not support fs type %s", fsType.c_str()); + + if (fsType == "ext4") { + formatCmds.push_back(it->second); + formatCmds.push_back("-F"); + formatCmds.push_back("-t"); + formatCmds.push_back(fsType); + formatCmds.push_back("-b"); + formatCmds.push_back(std::to_string(DEFAULT_BLOCK_SIZE)); + formatCmds.push_back(partPath_); + } else if (fsType == "f2fs") { + formatCmds.push_back(it->second); + formatCmds.push_back(partPath_); + } + return 0; +} + +bool Partition::IsOnlyErase() const +{ + std::vector rawPartName = { + "boot", "fastboot", "kernel", "misc", "system" + }; + auto it = std::find (rawPartName.begin(), rawPartName.end(), partName_); + return it != rawPartName.end(); +} + +uint32_t Partition::GetMountFlags(const std::string &mountFlagsStr, std::string &data) const +{ + static std::map mntInfo = { + { "ro", MS_RDONLY }, + { "rw", 0 }, + { ",sync", MS_SYNCHRONOUS }, + { ",dirsync", MS_DIRSYNC }, + { ",mand", MS_MANDLOCK }, + { ",lazytime", MS_LAZYTIME }, + { ",nosuid", MS_NOSUID }, + { ",nodev", MS_NODEV }, + { ",noexec", MS_NOEXEC }, + { ",noatime", MS_NOATIME }, + { ",nodiratime", MS_NODIRATIME }, + { ",relatime", MS_RELATIME }, + { ",remount", MS_REMOUNT }, + { ",bind", MS_BIND }, + { ",rec", MS_REC }, + { ",unbindable", MS_UNBINDABLE }, + { ",private", MS_PRIVATE }, + { ",slave", MS_SLAVE }, + { ",shared", MS_SHARED }, + { ",defaults", 0 }, + }; + + // get rw flags + uint32_t flags = 0; + std::string::size_type found = std::string::npos; + std::string::size_type start = 0; + while (true) { + found = mountFlagsStr.find_first_of(",", start + 1); + std::string option = mountFlagsStr.substr(start, found - start); + auto iter = mntInfo.find(option); + if (iter != mntInfo.end()) { + flags |= iter->second; + } else { + data.append(option); + data.append(","); + } + if (found == std::string::npos) { + break; + } + start = found; + } + data.pop_back(); // Remove last ',' + return flags; +} +} diff --git a/services/flashd/partition.h b/services/flashd/partition.h new file mode 100755 index 0000000000000000000000000000000000000000..411568f07480ab4a7e49ee49ceae76c920a1755d --- /dev/null +++ b/services/flashd/partition.h @@ -0,0 +1,82 @@ +/* + * 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 FLASHING_PARTITION_H +#define FLASHING_PARTITION_H +#include +#include +#include +#include +#include +#include "blockdevice.h" +#include "flash_utils.h" + +namespace flashd { +enum class PartitionType { + NORMAL, + LOGICAL, + EXTENDED, +}; + +class Partition { +public: + Partition(const std::string &name, const std::string &path, BlockDevicePtr device, FlashingPtr flash) + : partPath_(path), devName_(name), device_(device), flash_(flash) {} + ~Partition(); + + int Load(); + int DoFlash(const std::string &fileName); + int DoFormat(const std::string &fsType); + int DoErase(); + int DoResize(uint32_t blocks); + + bool IsOnlyErase() const; + const std::string GetPartitionName() const; + PartitionType GetPartitionType() const + { + return type_; + } + const std::string GetPartitionPath() const + { + return partPath_; + } +private: + std::string ReadPartitionSysInfo(const std::string &partition, + const std::string &type, std::vector &table); + int Open(); + int WriteRowData(int inputFd, size_t fileSize, std::vector &buffer, size_t dataSize); + int IsBlockDevice(int fd) const; + int GetMountInfo(); + int DoUmount(); + int DoMount(); + int BuildCommandParam(const std::string &fsType, std::vector &formatCmds) const; + uint64_t GetBlockDeviceSize(int fd) const; + uint32_t GetMountFlags(const std::string &mountFlagsStr, std::string &data) const; + + int fd_ = -1; + int partNumber_ { 0 }; // Partition number. + std::string partPath_ {}; + std::string devName_ {}; // partition DEVNAME + std::string partName_ {}; // partition PARTN + PartitionType type_ { PartitionType::NORMAL }; + std::string fsType_ {}; // File system type, ext4, f2fs etc. + std::string mountFlags_ {}; // flags:rw,relatime,fmask=0077,dmask=0077 + std::string mountPoint_ {}; + BlockDevicePtr device_ = nullptr; + FlashingPtr flash_ = nullptr; +}; +using PartitionPtr = Partition *; +} +#endif // FLASHING_PARTITION_H \ No newline at end of file diff --git a/services/fs_manager/BUILD.gn b/services/fs_manager/BUILD.gn index 3ce65a7c5343e9292f98f2f8d870afff8b48a98e..604e9096a4d9e691f54b754398cf3f4e563ba8c1 100644 --- a/services/fs_manager/BUILD.gn +++ b/services/fs_manager/BUILD.gn @@ -17,7 +17,6 @@ ohos_static_library("libfsmanager") { sources = [ "cmp_partition.cpp", "do_partition.cpp", - "fstab.cpp", "mount.cpp", "partitions.cpp", ] @@ -33,4 +32,8 @@ ohos_static_library("libfsmanager") { "//base/update/updater/utils:libutils", "//third_party/bounds_checking_function:libsec_static", ] + + external_deps = [ "init:libbegetutil" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/fs_manager/fstab.cpp b/services/fs_manager/fstab.cpp deleted file mode 100644 index 2851568b710dfb9f3ee4d2d260b0a91e02a6a0b2..0000000000000000000000000000000000000000 --- a/services/fs_manager/fstab.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * 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 "fs_manager/fstab.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include "fs_manager/fstab_api.h" -#include "log/log.h" -#include "utils.h" - -namespace updater { -using utils::SplitString; - -static std::map g_fsManagerMap = { - {"check", FS_MANAGER_CHECK}, - {"wait", FS_MANAGER_WAIT}, -}; - -void ParseFstabPerLine(std::string &line, Fstab &fstab, bool &parseError) -{ - const std::string separator = " \t"; - char *restPtr = nullptr; - struct FstabItem item; - char *p = nullptr; - do { - if ((p = strtok_r(const_cast(line.c_str()), separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse block device.\n"); - break; - } - - item.deviceName = p; - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse mount point.\n"); - break; - } - - item.mountPoint = p; - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse fs type.\n"); - break; - } - item.fsType = p; - - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse mount options.\n"); - break; - } - item.mountOptions = p; - - if ((p = strtok_r(nullptr, separator.c_str(), &restPtr)) == nullptr) { - fprintf(stderr, "Failed to parse fs manager flags.\n"); - break; - } - item.fsManagerFlags = 0; - std::string fsFlags = p; - for (const auto& flag : g_fsManagerMap) { - if (fsFlags.find(flag.first) != std::string::npos) { - item.fsManagerFlags |= flag.second; - } - } - - fstab.emplace_back(std::move(item)); - parseError = false; - } while (0); - - return; -} - -bool ReadFstabFromFile(const std::string &fstabFile, Fstab &fstab) -{ - char *line = nullptr; - size_t allocLen = 0; - ssize_t readLen = 0; - std::string tmpStr = ""; - Fstab tmpTab; - char *realPath = realpath(fstabFile.c_str(), NULL); - if (realPath == nullptr) { - return false; - } - auto fp = std::unique_ptr(fopen(realPath, "r"), fclose); - if (fp.get() == nullptr) { - LOG(ERROR) << "fp is nullptr"; - free(realPath); - return false; - } - free(realPath); - while ((readLen = getline(&line, &allocLen, fp.get())) != -1) { - char *p = nullptr; - if (line[readLen - 1] == '\n') { - line[readLen - 1] = '\0'; - } - p = line; - while (isspace(*p)) { - p++; - } - - if (*p == '\0' || *p == '#') { - continue; - } - - bool parseError = true; - tmpStr = p; - ParseFstabPerLine(tmpStr, tmpTab, parseError); - tmpStr.clear(); - if (parseError) { - free(line); - return false; - } - } - - free(line); - fstab = std::move(tmpTab); - return true; -} - -struct FstabItem* FindFstabItemForMountPoint(Fstab &fstab, const std::string& mp) -{ - for (auto &item : fstab) { - if (item.mountPoint == mp) { - return &item; - } - } - return nullptr; -} - -struct FstabItem* FindFstabItemForPath(Fstab &fstab, const std::string &path) -{ - struct FstabItem *item = nullptr; - std::string tmp(path); - if (path.empty()) { - return nullptr; - } - while (true) { - item = FindFstabItemForMountPoint(fstab, tmp); - if (item != nullptr) { - return item; - } - auto sep = tmp.find_last_of('/'); - if (sep == std::string::npos) { - return nullptr; - } - if (sep == 0) { - tmp = "/"; - break; - } - tmp = tmp.substr(0, sep); - } - return nullptr; -} - -static bool ParseDefaultMountFlags(const std::string &mountFlag, unsigned long &flags) -{ - std::map mountFlags = { - { "noatime", MS_NOATIME }, - { "noexec", MS_NOEXEC }, - { "nosuid", MS_NOSUID }, - { "nodev", MS_NODEV }, - { "nodiratime", MS_NODIRATIME }, - { "ro", MS_RDONLY }, - { "rw", 0 }, - { "sync", MS_SYNCHRONOUS }, - { "remount", MS_REMOUNT }, - { "bind", MS_BIND }, - { "rec", MS_REC }, - { "unbindable", MS_UNBINDABLE }, - { "private", MS_PRIVATE }, - { "slave", MS_SLAVE }, - { "shared", MS_SHARED }, - { "defaults", 0 }, - }; - for (const auto &flag : mountFlags) { - if (mountFlag == flag.first) { - flags = flag.second; - return true; - } - } - return false; -} - -unsigned long GetMountFlags(const std::string &mountOptions, std::string &fsSpecificOptions) -{ - unsigned long flags = 0; - unsigned long tmpFlag = 0; - - auto options = SplitString(mountOptions, ","); - fsSpecificOptions.clear(); - for (const auto &option : options) { - if (ParseDefaultMountFlags(option, tmpFlag)) { - flags |= tmpFlag; - } else { // not default mount flags, maybe File system specific. - fsSpecificOptions.append(option); - fsSpecificOptions.append(","); - } - } - fsSpecificOptions.pop_back(); // Remove last ',' - LOG(DEBUG) << "File system specific mount options is " << fsSpecificOptions; - return flags; -} -} // updater diff --git a/services/fs_manager/mount.cpp b/services/fs_manager/mount.cpp index 1053f2fad4c4fb013b1af32e5ba417b42f17ca2e..0a71611fd7b56546b29e177a9c16d9c511e611a0 100644 --- a/services/fs_manager/mount.cpp +++ b/services/fs_manager/mount.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "fs_manager/mount.h" #include #include @@ -21,166 +22,34 @@ #include #include #include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" #include "log/log.h" #include "utils.h" namespace updater { using updater::utils::SplitString; static std::string g_defaultUpdaterFstab = ""; -static Fstab g_fstab; - -static bool IsSupportedFilesystem(const std::string &fsType) -{ - std::vector supportedFilesystems = {"ext4", "f2fs", "vfat"}; - - bool supported = false; - for (const auto &fs : supportedFilesystems) { - if (fsType == fs) { - supported = true; - break; - } - } - return supported; -} - -static int ExecCommand(std::vector cmds) -{ - std::vector extractedCmds; - - for (const auto &cmd : cmds) { - extractedCmds.push_back(const_cast(cmd.c_str())); - } - extractedCmds.push_back(nullptr); - pid_t pid = fork(); - if (pid < 0) { - LOG(ERROR) << "Fork new process to format failed: " << errno; - ERROR_CODE(CODE_FORK_FAIL); - return -1; - } - if (pid == 0) { - execv(extractedCmds[0], extractedCmds.data()); - exit(-1); - } - int status; - waitpid(pid, &status, 0); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOG(ERROR) << "Command " << extractedCmds[0] << " failed with status " << WEXITSTATUS(status); - } - return WEXITSTATUS(status); -} - -static int DoFormat(const std::string &devPath, const std::string &fsType) -{ - std::map fsToolsMap = { - { "ext4", "/bin/mke2fs" }, - { "f2fs", "/bin/make_f2fs" }, - }; - int ret = 0; - auto it = fsToolsMap.find(fsType); - if (it == fsToolsMap.end()) { - LOG(ERROR) << "Can not find fs tools for " << fsType; - return -1; - } - auto fsTool = it->second; - if (fsType == "ext4") { - constexpr int blockSize = 4096; - std::vector formatCmds; - formatCmds.push_back(fsTool); - formatCmds.push_back("-F"); - formatCmds.push_back("-t"); - formatCmds.push_back(fsType); - formatCmds.push_back("-b"); - formatCmds.push_back(std::to_string(blockSize)); - formatCmds.push_back(devPath); - ret = ExecCommand(formatCmds); - } else if (fsType == "f2fs") { - std::vector formatCmds; - formatCmds.push_back(fsTool); - formatCmds.push_back(devPath); - ret = ExecCommand(formatCmds); - } - return ret; -} - -int FormatPartition(const std::string &path) -{ - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - if (item == nullptr) { - LOG(ERROR) << "Cannot find fstab item for " << path << " to format."; - return -1; - } - - if (item->mountPoint == "/") { - /* Can not format root */ - return 0; - } - - if (!IsSupportedFilesystem(item->fsType)) { - LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType; - return -1; - } - - // Umount first - if (UmountForPath(path) != 0) { - return -1; - } - int ret = DoFormat(item->deviceName, item->fsType); - if (ret != 0) { - LOG(ERROR) << "Format " << path << " failed"; - } - return ((ret != 0) ? -1 : 0); -} - -static MountStatus GetMountStatusForMountPoint(const std::string &mountPoint) +static Fstab *g_fstab; +static std::string GetFstabFile() { - char buffer[512]; - size_t n; - constexpr size_t numMountItems = 6; - const std::string mountFile = "/proc/mounts"; - auto fp = std::unique_ptr(fopen(mountFile.c_str(), "r"), fclose); - - while (fgets(buffer, sizeof(buffer) - 1, fp.get()) != nullptr) { - n = strlen(buffer); - if (buffer[n - 1] == '\n') { - buffer[n - 1] = '\0'; - } - std::string line(buffer); - std::vector mountItems = SplitString(line); - if (mountItems.size() == numMountItems) { - // Second item in /proc/mounts is mount point - if (mountItems[1] == mountPoint) { - return MountStatus::MOUNT_MOUNTED; - } + /* check vendor fstab files from specific directory */ + std::vector specificFstabFiles = {"/vendor/etc/fstab.updater"}; + for (auto& fstabFile : specificFstabFiles) { + if (access(fstabFile.c_str(), F_OK) == 0) { + return fstabFile; } } - - // Cannot find it from system. - return MountStatus::MOUNT_UMOUNTED; + return ""; } MountStatus GetMountStatusForPath(const std::string &path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); if (item == nullptr) { return MountStatus::MOUNT_ERROR; } return GetMountStatusForMountPoint(item->mountPoint); } -static std::string GetFstabFile() -{ - /* check vendor fstab files from specific directory */ - std::vector specificFstabFiles = {"/vendor/etc/fstab.updater", "/odm/etc/fstab.updater"}; - for (auto& fstabFile : specificFstabFiles) { - if (access(fstabFile.c_str(), F_OK) == 0) { - return fstabFile; - } - } - return ""; -} - void LoadFstab() { std::string fstabFile = g_defaultUpdaterFstab; @@ -191,22 +60,20 @@ void LoadFstab() } } // Clear fstab before read fstab file. - g_fstab.clear(); - if (ReadFstabFromFile(fstabFile, g_fstab) == false) { + if ((g_fstab = ReadFstabFromFile(fstabFile.c_str(), false)) == nullptr) { LOG(WARNING) << "Read " << fstabFile << " failed"; return; } LOG(DEBUG) << "Updater filesystem config info:"; - for (const auto &item : g_fstab) { - LOG(DEBUG) << "\tDevice: " << item.deviceName; - LOG(DEBUG) << "\tMount point : " << item.mountPoint; - LOG(DEBUG) << "\tFs type : " << item.fsType; - LOG(DEBUG) << "\tMount options: " << item.mountOptions; + for (FstabItem *item = g_fstab->head; item != nullptr; item = item->next) { + LOG(DEBUG) << "\tDevice: " << item->deviceName; + LOG(DEBUG) << "\tMount point : " << item->mountPoint; + LOG(DEBUG) << "\tFs type : " << item->fsType; + LOG(DEBUG) << "\tMount options: " << item->mountOptions; } } - void LoadSpecificFstab(const std::string &fstabName) { g_defaultUpdaterFstab = fstabName; @@ -216,21 +83,20 @@ void LoadSpecificFstab(const std::string &fstabName) int UmountForPath(const std::string& path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - MountStatus rc; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); if (item == nullptr) { LOG(ERROR) << "Cannot find fstab item for " << path << " to umount."; return -1; } LOG(DEBUG) << "Umount for path " << path; - rc = GetMountStatusForMountPoint(item->mountPoint); - if (rc == MountStatus::MOUNT_ERROR) { + MountStatus rc = GetMountStatusForMountPoint(item->mountPoint); + if (rc == MOUNT_ERROR) { return -1; - } else if (rc == MountStatus::MOUNT_UMOUNTED) { + } else if (rc == MOUNT_UMOUNTED) { return 0; } else { - int ret = umount(item->mountPoint.c_str()); + int ret = umount(item->mountPoint); if (ret == -1) { LOG(ERROR) << "Umount " << item->mountPoint << "failed: " << errno; return -1; @@ -239,54 +105,10 @@ int UmountForPath(const std::string& path) return 0; } -static int Mount(const std::string &source, const std::string &target, const std::string &fsType, - unsigned long flags, const std::string &data) -{ - struct stat st {}; - int rc; - if (stat(target.c_str(), &st) != 0 && errno != ENOENT) { - LOG(ERROR) << "Cannot get " << target << " status: " << errno; - return -1; - } - if ((st.st_mode & S_IFMT) == S_IFLNK) { // link, delete it. - unlink(target.c_str()); - } - mkdir(target.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - errno = 0; - while ((rc = mount(source.c_str(), target.c_str(), fsType.c_str(), flags, data.c_str()) != 0)) { - if (errno == EAGAIN) { - LOG(INFO) << "Mount " << source << " to " << target << " failed. try again"; - continue; - } else { - break; - } - } - return rc; -} - -static int DoMount(const struct FstabItem &item) -{ - unsigned long mountFlags; - std::string fsSpecificOptions; - - mountFlags = GetMountFlags(item.mountOptions, fsSpecificOptions); - if (!IsSupportedFilesystem(item.fsType)) { - LOG(ERROR) << "Unsupported file system \"" << item.fsType << "\""; - return -1; - } - int rc = Mount(item.deviceName, item.mountPoint, item.fsType, mountFlags, fsSpecificOptions); - if (rc != 0) { - LOG(ERROR) << "Mount " << item.deviceName << " to " << item.mountPoint << " failed: " << errno; - } else { - LOG(INFO) << "Mount " << item.deviceName << " to " << item.mountPoint << " successful"; - } - return rc; -} - int MountForPath(const std::string &path) { - struct FstabItem *item = FindFstabItemForPath(g_fstab, path); - int ret; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); + int ret = -1; if (item == nullptr) { LOG(ERROR) << "Cannot find fstab item for " << path << " to mount."; return -1; @@ -295,51 +117,68 @@ int MountForPath(const std::string &path) LOG(DEBUG) << "Mount for path " << path; MountStatus rc = GetMountStatusForMountPoint(item->mountPoint); if (rc == MountStatus::MOUNT_ERROR) { - return -1; + ret = -1; } else if (rc == MountStatus::MOUNT_MOUNTED) { - std::cout << path << " already mounted\n"; - return 0; + LOG(INFO) << path << " already mounted"; + ret = 0; } else { - ret = DoMount(*item); + ret = MountOneItem(item); } return ret; } -struct FstabItem *GetItemForMountPoint(const std::string &mountPoint) +int FormatPartition(const std::string &path) { - if (g_fstab.empty()) { - LOG(ERROR) << "Fstab is empty."; - return nullptr; + FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str()); + if (item == nullptr) { + LOG(ERROR) << "Cannot find fstab item for " << path << " to format."; + return -1; } - for (auto& item : g_fstab) { - if (item.mountPoint == mountPoint) { - return &item; - } + + if (strcmp(item->mountPoint, "/") == 0) { + /* Can not format root */ + return 0; } - return nullptr; + + if (!IsSupportedFilesystem(item->fsType)) { + LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType; + return -1; + } + + // Umount first + if (UmountForPath(path) != 0) { + return -1; + } + int ret = DoFormat(item->deviceName, item->fsType); + if (ret != 0) { + LOG(ERROR) << "Format " << path << " failed"; + } + return ((ret != 0) ? -1 : 0); } int SetupPartitions() { - if (g_fstab.empty()) { - LOG(ERROR) << "Fstab is empty."; + if (g_fstab == NULL || g_fstab->head == NULL) { + LOG(ERROR) << "Fstab is invalid"; return -1; } - for (const auto &item : g_fstab) { - if (item.mountPoint == "/" || item.mountPoint == "/tmp" || item.fsType == "none" || - item.mountPoint == "/sdcard") { + for (const FstabItem *item = g_fstab->head; item != nullptr; item = item->next) { + std::string mountPoint(item->mountPoint); + std::string fsType(item->fsType); + if (mountPoint == "/" || mountPoint == "/tmp" || fsType == "none" || + mountPoint == "/sdcard") { continue; } - if (item.mountPoint == "/data") { - if (MountForPath(item.mountPoint) != 0) { - LOG(ERROR) << "Expected partition " << item.mountPoint << " is not mounted."; + if (mountPoint == "/data") { + if (MountForPath(mountPoint) != 0) { + LOG(ERROR) << "Expected partition " << mountPoint << " is not mounted."; return -1; } continue; } - if (UmountForPath(item.mountPoint) != 0) { - LOG(ERROR) << "Umount " << item.mountPoint << " failed"; + if (UmountForPath(mountPoint) != 0) { + LOG(ERROR) << "Umount " << mountPoint << " failed"; return -1; } } @@ -350,12 +189,11 @@ const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint) { std::string blockDevice = ""; if (!mountPoint.empty()) { - auto item = FindFstabItemForMountPoint(g_fstab, mountPoint); - if (item) { + FstabItem *item = FindFstabItemForMountPoint(*g_fstab, mountPoint.c_str()); + if (item != NULL) { blockDevice = item->deviceName; } } return blockDevice; } } // updater - diff --git a/services/include/applypatch/block_set.h b/services/include/applypatch/block_set.h index a59f3956139e726813621a74b9ccdec921fbbdd2..34f89b964a537256dfbb50d03bf1e3229e88d0dc 100644 --- a/services/include/applypatch/block_set.h +++ b/services/include/applypatch/block_set.h @@ -41,6 +41,8 @@ public: } explicit BlockSet(std::vector &&pairs); + + ~BlockSet() {} // Insert block to set after parsing from a string type or vector type bool ParserAndInsert(const std::string &blockStr); diff --git a/services/include/applypatch/partition_record.h b/services/include/applypatch/partition_record.h index 916863f45de28cf357cdddb2aa830e24ba7cc3ca..962d43f4aaf2f5ce20976691409361d8ee30cb77 100644 --- a/services/include/applypatch/partition_record.h +++ b/services/include/applypatch/partition_record.h @@ -68,11 +68,11 @@ private: private: std::string GetMiscPartitionPath(const std::string &mountPoint = "/misc"); - PartitionRecordInfo info_; + PartitionRecordInfo info_ {}; // offset of partition record in misc. // offset is not start from zero, but // start from the global offset of misc partition. - size_t offset_; + off_t offset_; }; } // namespace updater -#endif // UPDATER_PARTITION_UPDATE_RECORD_H \ No newline at end of file +#endif // UPDATER_PARTITION_UPDATE_RECORD_H diff --git a/services/include/applypatch/transfer_manager.h b/services/include/applypatch/transfer_manager.h index 4d63a04dc568f0f4a3ad7d2d0097577a520ba7a8..b2e06bdbad476b0bed2e25f537b587e6bce01ac2 100644 --- a/services/include/applypatch/transfer_manager.h +++ b/services/include/applypatch/transfer_manager.h @@ -50,6 +50,7 @@ struct TransferParams { std::unique_ptr writerThreadInfo; int storeCreated; std::string storeBase; + std::string retryFile; uint8_t *patchDataBuffer; size_t patchDataSize; }; @@ -72,6 +73,7 @@ public: } std::string ReloadForRetry() const; bool CheckResult(const CommandResult result, const std::string &cmd, const CommandType &type); + bool NeedSetProgress(const CommandType &type); private: bool RegisterForRetry(const std::string &cmd); diff --git a/services/include/applypatch/updater_env.h b/services/include/applypatch/updater_env.h index 4ce1b8f70ed1fbbc2fdbb96eecbfb32c353d3bb2..121e1a4dbc38003d8aad4925e9c92d6050923677 100644 --- a/services/include/applypatch/updater_env.h +++ b/services/include/applypatch/updater_env.h @@ -22,6 +22,7 @@ #include "package/pkg_manager.h" #include "script_instruction.h" #include "script_manager.h" +#include "updater/updater.h" using uscript::UScriptEnv; using uscript::UScriptInstructionFactory; @@ -30,8 +31,8 @@ using uscript::UScriptInstructionFactoryPtr; namespace updater { class UpdaterEnv : public UScriptEnv { public: - UpdaterEnv(hpackage::PkgManager::PkgManagerPtr pkgManager, FILE* pipeWrite, bool retry) : - UScriptEnv(pkgManager), pipeWrite_(pipeWrite), isRetry_(retry) {} + UpdaterEnv(hpackage::PkgManager::PkgManagerPtr pkgManager, PostMessageFunction postMessage, bool retry) + : UScriptEnv(pkgManager), postMessage_(postMessage), isRetry_(retry) {} virtual ~UpdaterEnv(); virtual void PostMessage(const std::string &cmd, std::string content); @@ -43,7 +44,7 @@ public: } private: UScriptInstructionFactoryPtr factory_ = nullptr; - FILE* pipeWrite_ = nullptr; + PostMessageFunction postMessage_ = nullptr; bool isRetry_ = false; }; } diff --git a/services/include/flashd/flashd.h b/services/include/flashd/flashd.h new file mode 100755 index 0000000000000000000000000000000000000000..13af85572eead70ec00cf46f3fe7789310ea1213 --- /dev/null +++ b/services/include/flashd/flashd.h @@ -0,0 +1,83 @@ +/* + * 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_FLASHING_H +#define UPDATER_FLASHING_H +#include +#include + +namespace flashd { +enum { + FLASHING_SYSTEM_ERROR = 100, + FLASHING_ARG_INVALID, + FLASHING_IMAGE_INVALID, + FLASHING_PART_NOEXIST, + FLASHING_NOPERMISSION, + FLASHING_PART_WRITE_ERROR, + FLASHING_PACKAGE_INVALID, + FLASHING_SPACE_NOTENOUGH, + FLASHING_INVALID_SPACE, + FLASHING_FSTYPE_NOT_SUPPORT, +}; + +enum UpdateModType { + UPDATEMOD_UPDATE, + UPDATEMOD_FLASH, + UPDATEMOD_ERASE, + UPDATEMOD_FORMAT, + UPDATEMOD_MAX +}; + +static constexpr uint16_t MAX_SIZE_BUF = 1024; +static constexpr uint32_t PERCENT_FINISH = 100; +static constexpr uint32_t PERCENT_CLEAR = (uint32_t)-1; + +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 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 = 2048; +static constexpr uint32_t DEFAULT_SIZE_UNIT = 1024 * 1024; + +using FlashHandle = void *; +int flashd_main(int argc, char **argv); +using ProgressFunction = std::function; + +int CreateFlashInstance(FlashHandle *handle, std::string &errorMsg, ProgressFunction progressor); +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/fs_manager/mount.h b/services/include/fs_manager/mount.h index 7d70ccbbb839a3470fd8e511bee30a65108f352f..744a8d1363015abd1f9d0f06fb9d1c047187ccfe 100644 --- a/services/include/fs_manager/mount.h +++ b/services/include/fs_manager/mount.h @@ -16,24 +16,16 @@ #define UPDATER_FS_MANAGER_MOUNT_H #include -#include "fs_manager/fstab_api.h" -#include "fs_manager/fstab.h" +#include "fs_manager/fs_manager.h" namespace updater { -enum MountStatus : int { - MOUNT_ERROR = -1, - MOUNT_UMOUNTED = 0, - MOUNT_MOUNTED = 1, -}; - void LoadFstab(); /* Load fstab */ void LoadSpecificFstab(const std::string &fstabName); int FormatPartition(const std::string &path); int UmountForPath(const std::string &path); int MountForPath(const std::string &path); -MountStatus GetMountStatusForPath(const std::string &path); -struct FstabItem *GetItemForMountPoint(const std::string &mountPoint); int SetupPartitions(); const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint); +MountStatus GetMountStatusForPath(const std::string &path); } // updater #endif // UPDATER_FS_MANAGER_MOUNT_H \ No newline at end of file diff --git a/services/include/package/pkg_manager.h b/services/include/package/pkg_manager.h index 9cf37201c23978115e9d841ab1949d53efe46af0..e70c9d8dbeafdf1f0b38c50c554d6fb12efb65d6 100644 --- a/services/include/package/pkg_manager.h +++ b/services/include/package/pkg_manager.h @@ -47,6 +47,13 @@ enum { PKG_VERIFY_FAIL, }; +enum { + POST_TYPE_UPLOAD_PKG = 0, + POST_TYPE_DECODE_PKG, + POST_TYPE_VERIFY_PKG, + POST_TYPE_WRITE_PARTITION +}; + /** * Package information */ @@ -203,6 +210,8 @@ public: } }; +using PkgDecodeProgress = std::function; + /** * Get a singleton PkgManager instance. */ @@ -334,6 +343,10 @@ public: std::vector &fileIds) = 0; virtual int32_t ParsePackage(StreamPtr stream, std::vector &fileIds, int32_t type) = 0; + + virtual void SetPkgDecodeProgress(PkgDecodeProgress decodeProgress) = 0; + + virtual void PostDecodeProgress(int type, size_t writeDataLen, const void *context) = 0; }; } // namespace hpackage #endif // PKG_MANAGER_H diff --git a/services/include/updater/updater.h b/services/include/updater/updater.h index e71b1b9ca55b1fc9039bb5516f5c05ea971a2c56..272c301ac6afab32d28b9a1248a090306bf164e9 100644 --- a/services/include/updater/updater.h +++ b/services/include/updater/updater.h @@ -26,9 +26,12 @@ enum UpdaterStatus { UPDATE_CORRUPT, /* package or verify failed, something is broken. */ UPDATE_SKIP, /* skip update because of condition is not satisfied, e.g, battery is low */ UPDATE_RETRY, + UPDATE_SPACE_NOTENOUGH, UPDATE_UNKNOWN }; +using PostMessageFunction = std::function; + UpdaterStatus DoInstallUpdaterPackage(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, int retryCount); @@ -38,5 +41,21 @@ UpdaterStatus StartUpdaterProc(hpackage::PkgManager::PkgManagerPtr pkgManager, c int GetUpdatePackageInfo(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string& path); int UpdatePreProcess(hpackage::PkgManager::PkgManagerPtr pkgManager, const std::string& path); + +int ExecUpdate(hpackage::PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunction postMessage); + +bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog); + +void CompressLogs(const std::string &name); + +int IsSpaceCapacitySufficient(const std::string &packagePath); + +bool IsSDCardExist(const std::string &sdcard_path); + +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 d6b862d498404300be1535b2426e4769d3fcd364..6b447687201e76eb889baabf32d68f4300f15302 100644 --- a/services/include/updater/updater_const.h +++ b/services/include/updater/updater_const.h @@ -22,14 +22,13 @@ const std::string COMMAND_FILE = "/data/updater/command"; const std::string TMP_LOG = "/tmp/updater.log"; const std::string TMP_STAGE_LOG = "/tmp/updater_stage.log"; const std::string TMP_ERROR_CODE_PATH = "/tmp/error_code.log"; -const std::string ERROR_CODE_PATH = "/data/updater/log/error_code.log"; const std::string UPDATER_LOG_DIR = "/data/updater/log"; -const std::string UPDATER_LOG = "/data/updater/log/updater_log"; -const std::string UPDATER_STAGE_LOG = "/data/updater/log/updater_stage_log"; const std::string UPDATER_PATH = "/data/updater"; const std::string MISC_FILE = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc"; const std::string UPDATER_BINARY = "updater_binary"; const std::string SDCARD_PATH = "/sdcard"; +const std::string UPDATER_HDC_LOG = "/data/updater/log/flashd_hdc.log"; + #ifndef UPDATER_UT const std::string SDCARD_CARD_PATH = "/sdcard/updater"; const std::string SDCARD_CARD_PKG_PATH = "/sdcard/updater/updater.zip"; @@ -76,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/log/BUILD.gn b/services/log/BUILD.gn index a063f69d4bf11ffdb8a55502a6a45022c303222d..f4d07de8e42a6a9140556f8001d37e18f13688c5 100644 --- a/services/log/BUILD.gn +++ b/services/log/BUILD.gn @@ -23,4 +23,6 @@ ohos_static_library("libupdaterlog") { ] deps = [ "//third_party/bounds_checking_function:libsec_static" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/main.cpp b/services/main.cpp index 322f128c3595fcbb7f9108a7122b2489e62c09c4..6f5d5fe974b1d11727ca786b969a31550dae10a7 100644 --- a/services/main.cpp +++ b/services/main.cpp @@ -12,10 +12,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "fs_manager/mount.h" +#include "flashd/flashd.h" +#include "log/log.h" +#include "misc_info/misc_info.h" +#include "updater/updater_const.h" #include "updater_main.h" +using namespace updater; + int main(int argc, char **argv) { + int mode = BOOT_UPDATER; + int ret = GetBootMode(mode); + if (ret != 0) { + printf("Failed to get boot mode, start updater mode \n"); + mode = BOOT_UPDATER; + } + + InitUpdaterLogger((mode == BOOT_FLASHD) ? "FLASHD" : "UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); + SetLogLevel(INFO); + LoadFstab(); + 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/BUILD.gn b/services/package/BUILD.gn index d947f2f836ea36b3d07ddd58dd9452dc0e003087..142054f0ff68aa3ece976ce8785228ecafea00cb 100644 --- a/services/package/BUILD.gn +++ b/services/package/BUILD.gn @@ -58,4 +58,6 @@ ohos_static_library("libupdaterpackage") { deps = [ "//third_party/bounds_checking_function:libsec_static" ] configs = [ ":package_config" ] + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/package/pkg_algorithm/pkg_algo_digest.cpp b/services/package/pkg_algorithm/pkg_algo_digest.cpp index 1855aa675b9978b88673b6641b7b943010f4ba49..4bb6eef67b32ac66d9743c6d81dae1b381d58cec 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_); @@ -147,7 +151,6 @@ DigestAlgorithm::DigestAlgorithmPtr PkgAlgorithmFactory::GetDigestAlgorithm(uint return std::make_shared(); default: return std::make_shared(); - break; } return nullptr; } 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_algorithm/pkg_algorithm.cpp b/services/package/pkg_algorithm/pkg_algorithm.cpp index 61163e7304038d89563b674de9f91ac4969703d2..1062b4fa30218e47bee9b85cd7383b667119126a 100644 --- a/services/package/pkg_algorithm/pkg_algorithm.cpp +++ b/services/package/pkg_algorithm/pkg_algorithm.cpp @@ -78,7 +78,7 @@ int32_t PkgAlgorithm::Pack(const PkgStreamPtr inStream, const PkgStreamPtr outSt ret = FinalDigest(algorithm, context, true); PKG_CHECK(ret == 0, return ret, "Check digest fail"); - PKG_CHECK(srcOffset - context.srcOffset == context.unpackedSize, return ret, + PKG_CHECK(srcOffset - context.srcOffset == context.unpackedSize, return PKG_INVALID_STREAM, "original size error %zu %zu", srcOffset, context.unpackedSize); context.packedSize = destOffset - context.destOffset; return ret; @@ -110,7 +110,7 @@ int32_t PkgAlgorithm::Unpack(const PkgStreamPtr inStream, const PkgStreamPtr out ret = FinalDigest(algorithm, context, true); PKG_CHECK(ret == 0, return ret, "Check digest fail"); - PKG_CHECK(destOffset - context.destOffset == context.packedSize, return ret, + PKG_CHECK(destOffset - context.destOffset == context.packedSize, return PKG_INVALID_STREAM, "original size error %zu %zu", destOffset, context.packedSize); context.unpackedSize = srcOffset - context.srcOffset; return ret; diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index 8dbff31c3a63557ed9cfa36301b63726e828a0bb..aa8951571be69499d6925c0952d3113476ce4e2c 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -52,7 +52,9 @@ PkgManager::PkgManagerPtr PkgManager::GetPackageInstance() PkgManager::PkgManagerPtr PkgManager::CreatePackageInstance() { - return new PkgManagerImpl(); + PkgManager::PkgManagerPtr impl = new PkgManagerImpl(); + PKG_LOGI("CreatePackageInstance %p", impl); + return impl; } void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager) @@ -60,6 +62,7 @@ void PkgManager::ReleasePackageInstance(PkgManager::PkgManagerPtr manager) if (manager == nullptr) { return; } + PKG_LOGI("ReleasePackageInstance %p", manager); if (g_pkgManagerInstance == manager) { delete g_pkgManagerInstance; g_pkgManagerInstance = nullptr; @@ -101,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; @@ -117,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; @@ -133,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; @@ -205,16 +211,16 @@ PkgFilePtr PkgManagerImpl::CreatePackage(PkgStreamPtr stream, PkgFile::PkgType t PkgFilePtr pkgFile = nullptr; switch (type) { case PkgFile::PKG_TYPE_UPGRADE: - pkgFile = new UpgradePkgFile(stream, header); + pkgFile = new UpgradePkgFile(this, stream, header); break; case PkgFile::PKG_TYPE_ZIP: - pkgFile = new ZipPkgFile(stream); + pkgFile = new ZipPkgFile(this, stream); break; case PkgFile::PKG_TYPE_LZ4: - pkgFile = new Lz4PkgFile(stream); + pkgFile = new Lz4PkgFile(this, stream); break; case PkgFile::PKG_TYPE_GZIP: - pkgFile = new GZipPkgFile(stream); + pkgFile = new GZipPkgFile(this, stream); break; default: return nullptr; @@ -396,7 +402,7 @@ int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fi int32_t PkgManagerImpl::CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) { - PkgStreamPtr pkgStream = new MemoryMapStream(fileName, buffer, PkgStream::PkgStreamType_Buffer); + PkgStreamPtr pkgStream = new MemoryMapStream(this, fileName, buffer, PkgStream::PkgStreamType_Buffer); PKG_CHECK(pkgStream != nullptr, return -1, "Failed to create stream"); stream = pkgStream; return PKG_SUCCESS; @@ -438,7 +444,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string FILE *file = nullptr; file = fopen(fileName.c_str(), modeFlags[type]); PKG_CHECK(file != nullptr, return PKG_INVALID_FILE, "Fail to open file %s ", fileName.c_str()); - stream = new FileStream(fileName, file, type); + stream = new FileStream(this, fileName, file, type); } else if (type == PkgStream::PkgStreamType_MemoryMap) { size_t fileSize = size; if (fileSize == 0) { @@ -451,7 +457,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string uint8_t *memoryMap = MapMemory(fileName, fileSize); PKG_CHECK(memoryMap != nullptr, return PKG_INVALID_FILE, "Fail to map memory %s ", fileName.c_str()); PkgBuffer buffer(memoryMap, fileSize); - stream = new MemoryMapStream(fileName, buffer); + stream = new MemoryMapStream(this, fileName, buffer); } else { return -1; } @@ -462,7 +468,7 @@ int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string int32_t PkgManagerImpl::CreatePkgStream(PkgStreamPtr &stream, const std::string &fileName, PkgStream::ExtractFileProcessor processor, const void *context) { - stream = new ProcessorStream(fileName, processor, context); + stream = new ProcessorStream(this, fileName, processor, context); PKG_CHECK(stream != nullptr, return -1, "Failed to create stream"); return PKG_SUCCESS; } @@ -588,6 +594,7 @@ int32_t PkgManagerImpl::GenerateFileDigest(PkgStreamPtr stream, PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_HAS_SIGN, algorithm->Update(buff, readLen)); PKG_IS_TRUE_DONE(flags & DIGEST_FLAGS_NO_SIGN, algorithmInner->Update(buff, readLen)); offset += readLen; + PostDecodeProgress(POST_TYPE_VERIFY_PKG, readLen, nullptr); readLen = 0; } @@ -677,8 +684,8 @@ int32_t PkgManagerImpl::DecompressBuffer(FileInfoPtr info, const PkgBuffer &data PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info); PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str()); - std::shared_ptr inStream = std::make_shared(info->identity, - data, PkgStream::PkgStreamType_Buffer); + std::shared_ptr inStream = std::make_shared( + (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer); PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str()); PkgAlgorithmContext context = {{0, 0}, {data.length, 0}, 0, info->digestMethod}; int32_t ret = algorithm->Unpack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context); @@ -698,8 +705,8 @@ int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &data, PkgAlgorithm::PkgAlgorithmPtr algorithm = PkgAlgorithmFactory::GetAlgorithm(info); PKG_CHECK(algorithm != nullptr, return PKG_INVALID_PARAM, "Can not get algorithm for %s", info->identity.c_str()); - std::shared_ptr inStream = std::make_shared(info->identity, - data, PkgStream::PkgStreamType_Buffer); + std::shared_ptr inStream = std::make_shared( + (PkgManager::PkgManagerPtr)this, info->identity, data, PkgStream::PkgStreamType_Buffer); PKG_CHECK(inStream != nullptr, return PKG_INVALID_PARAM, "Can not create stream for %s", info->identity.c_str()); PkgAlgorithmContext context = {{0, 0}, {0, data.length}, 0, info->digestMethod}; int32_t ret = algorithm->Pack(inStream.get(), PkgStreamImpl::ConvertPkgStream(output), context); @@ -710,4 +717,11 @@ int32_t PkgManagerImpl::CompressBuffer(FileInfoPtr info, const PkgBuffer &data, info->unpackedSize = context.unpackedSize; return PKG_SUCCESS; } + +void PkgManagerImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) +{ + if (decodeProgress_ != nullptr) { + decodeProgress_(type, writeDataLen, context); + } +} } // namespace hpackage diff --git a/services/package/pkg_manager/pkg_manager_impl.h b/services/package/pkg_manager/pkg_manager_impl.h index 1233bb431e747557b291b96650985fd0bfff7b48..04dd1039bc7c979e6fd6f28d5c815c10eca88f1a 100644 --- a/services/package/pkg_manager/pkg_manager_impl.h +++ b/services/package/pkg_manager/pkg_manager_impl.h @@ -73,6 +73,13 @@ public: int32_t ParsePackage(StreamPtr stream, std::vector &fileIds, int32_t type) override; int32_t CreatePkgStream(StreamPtr &stream, const std::string &fileName, const PkgBuffer &buffer) override; + + void SetPkgDecodeProgress(PkgDecodeProgress decodeProgress) override + { + decodeProgress_ = decodeProgress; + } + + void PostDecodeProgress(int type, size_t writeDataLen, const void *context) override; private: PkgFilePtr CreatePackage(PkgStreamPtr stream, PkgFile::PkgType type, PkgInfoPtr header = nullptr); @@ -111,6 +118,7 @@ private: std::vector pkgFiles_ {}; std::map pkgStreams_ {}; std::string signVerifyKeyName_ {}; + PkgDecodeProgress decodeProgress_ { nullptr }; }; } // namespace hpackage #endif // PKG_MANAGER_IMPL_H diff --git a/services/package/pkg_manager/pkg_stream.cpp b/services/package/pkg_manager/pkg_stream.cpp index ab2cda418d9456df560313b4138f03611d384c05..7f28de2fcd46d8e99f10e9a3238a784f888ece43 100644 --- a/services/package/pkg_manager/pkg_stream.cpp +++ b/services/package/pkg_manager/pkg_stream.cpp @@ -18,6 +18,7 @@ #include #include #include "pkg_manager.h" +#include "pkg_manager_impl.h" #include "pkg_utils.h" #include "securec.h" @@ -47,6 +48,13 @@ bool PkgStreamImpl::IsRef() const return refCount_ == 0; } +void PkgStreamImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) +{ + if (pkgManager_ != nullptr) { + pkgManager_->PostDecodeProgress(type, writeDataLen, context); + } +} + FileStream::~FileStream() { if (stream_ != nullptr) { @@ -76,6 +84,7 @@ int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t offset) fseek(stream_, offset, SEEK_SET); size_t len = fwrite(data.buffer, size, 1, stream_); PKG_CHECK(len == 1, return PKG_INVALID_STREAM, "Write buffer fail"); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); return PKG_SUCCESS; } @@ -84,7 +93,12 @@ size_t FileStream::GetFileLength() PKG_CHECK(stream_ != nullptr, return 0, "Invalid stream"); if (fileLength_ == 0) { PKG_CHECK(Seek(0, SEEK_END) == 0, return -1, "Invalid stream"); - fileLength_ = ftell(stream_); + off_t pos = ftello(stream_); + if (pos < 0) { + PKG_LOGE("Failed to get file length, err = %d", errno); + return 0; + } + fileLength_ = static_cast(pos); fseek(stream_, 0, SEEK_SET); } return fileLength_; @@ -102,11 +116,6 @@ int32_t FileStream::Flush(size_t size) if (fileLength_ == 0) { fileLength_ = size; } - fseek(stream_, 0, SEEK_END); - fileLength_ = ftell(stream_); - if (size != fileLength_) { - PKG_LOGE("Flush size %zu local size:%zu", size, fileLength_); - } PKG_CHECK(fflush(stream_) == 0, return PKG_INVALID_STREAM, "Invalid stream"); return PKG_SUCCESS; } @@ -143,6 +152,7 @@ int32_t MemoryMapStream::Write(const PkgBuffer &data, size_t size, size_t start) PKG_CHECK(copyLen >= size, return PKG_INVALID_STREAM, "Write fail copyLen %zu, %zu", copyLen, size); int32_t ret = memcpy_s(memMap_ + currOffset_, memSize_ - currOffset_, data.buffer, size); PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_STREAM, "Write fail"); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); return PKG_SUCCESS; } diff --git a/services/package/pkg_manager/pkg_stream.h b/services/package/pkg_manager/pkg_stream.h index 18f06ae78146f8598018c798c0c6ad049d0c642a..02d21feb7d9c8c726904c0728507ee33f517dbf8 100644 --- a/services/package/pkg_manager/pkg_stream.h +++ b/services/package/pkg_manager/pkg_stream.h @@ -27,7 +27,8 @@ class PkgStreamImpl; using PkgStreamPtr = PkgStreamImpl *; class PkgStreamImpl : public PkgStream { public: - explicit PkgStreamImpl(std::string fileName) : fileName_(fileName), refCount_(0) {} + explicit PkgStreamImpl(PkgManager::PkgManagerPtr pkgManager, std::string fileName) + : fileName_(fileName), refCount_(0), pkgManager_(pkgManager) {} virtual ~PkgStreamImpl() {} @@ -68,16 +69,18 @@ public: static PkgStreamPtr ConvertPkgStream(PkgManager::StreamPtr stream); protected: + void PostDecodeProgress(int type, size_t writeDataLen, const void *context); std::string fileName_; private: std::atomic_int refCount_; + PkgManager::PkgManagerPtr pkgManager_ = nullptr; }; class FileStream : public PkgStreamImpl { public: - FileStream(std::string fileName, FILE *stream, int32_t streamType) : PkgStreamImpl(fileName), - stream_(stream), fileLength_(0), streamType_(streamType) {} + FileStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, FILE *stream, int32_t streamType) + : PkgStreamImpl(pkgManager, fileName), stream_(stream), fileLength_(0), streamType_(streamType) {} ~FileStream() override; @@ -103,8 +106,8 @@ private: class MemoryMapStream : public PkgStreamImpl { public: - MemoryMapStream(std::string fileName, const PkgBuffer &buffer, - int32_t streamType = PkgStreamType_MemoryMap) : PkgStreamImpl(fileName), memMap_(buffer.buffer), + MemoryMapStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, const PkgBuffer &buffer, + int32_t streamType = PkgStreamType_MemoryMap) : PkgStreamImpl(pkgManager, fileName), memMap_(buffer.buffer), memSize_(buffer.length), currOffset_(0), streamType_(streamType) {} ~MemoryMapStream() override; @@ -151,8 +154,9 @@ private: class ProcessorStream : public PkgStreamImpl { public: - ProcessorStream(std::string fileName, ExtractFileProcessor processor, const void *context) - : PkgStreamImpl(fileName), processor_(processor), context_(context) {} + ProcessorStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName, + ExtractFileProcessor processor, const void *context) + : PkgStreamImpl(pkgManager, fileName), processor_(processor), context_(context) {} ~ProcessorStream() override {} @@ -168,7 +172,9 @@ public: int32_t Write(const PkgBuffer &data, size_t size, size_t start) override { PKG_CHECK(processor_ != nullptr, return PKG_INVALID_STREAM, "processor not exist"); - return processor_(data, size, start, false, context_); + int ret = processor_(data, size, start, false, context_); + PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); + return ret; } int32_t Seek(long int size, int whence) override diff --git a/services/package/pkg_package/pkg_gzipfile.h b/services/package/pkg_package/pkg_gzipfile.h index 8d14f3ac2a62cfe0a99f1d3e1f87ad17b6eb4a6e..a06dd7e55223092abef49a778413f27d20e4f17b 100644 --- a/services/package/pkg_package/pkg_gzipfile.h +++ b/services/package/pkg_package/pkg_gzipfile.h @@ -56,7 +56,8 @@ private: class GZipPkgFile : public PkgFile { public: - explicit GZipPkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_GZIP) + explicit GZipPkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_GZIP) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; 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/package/pkg_package/pkg_lz4file.h b/services/package/pkg_package/pkg_lz4file.h index 244255296e73ce618360fe6c162fe568815d8495..95b0658a0f4093f0b26f55bbcc24342982e4ba7f 100644 --- a/services/package/pkg_package/pkg_lz4file.h +++ b/services/package/pkg_package/pkg_lz4file.h @@ -52,7 +52,8 @@ private: class Lz4PkgFile : public PkgFile { public: - explicit Lz4PkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_LZ4) + explicit Lz4PkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_LZ4) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; diff --git a/services/package/pkg_package/pkg_pkgfile.cpp b/services/package/pkg_package/pkg_pkgfile.cpp index afa0724da87b1f1b325ebeb2da26e352fe8347ae..c02e9d8c174a4a88fc4143e3847ad6cbdc48df2f 100644 --- a/services/package/pkg_package/pkg_pkgfile.cpp +++ b/services/package/pkg_package/pkg_pkgfile.cpp @@ -35,7 +35,7 @@ PkgFile::~PkgFile() pkgEntryMapId_.clear(); pkgEntryMapFileName_.clear(); PkgManager::StreamPtr tmpStream = pkgStream_; - PkgManager::GetPackageInstance()->ClosePkgStream(tmpStream); + pkgManager_->ClosePkgStream(tmpStream); } PkgEntryPtr PkgFile::AddPkgEntry(const std::string &fileName) diff --git a/services/package/pkg_package/pkg_pkgfile.h b/services/package/pkg_package/pkg_pkgfile.h index e48b23690004169e614fc5234ed57a0877622b4c..7a7a908d1aea5d12ff940681c42cc12765d89712 100644 --- a/services/package/pkg_package/pkg_pkgfile.h +++ b/services/package/pkg_package/pkg_pkgfile.h @@ -85,7 +85,8 @@ public: const std::vector &digest, const std::vector &signature)>; public: - PkgFile(PkgStreamPtr stream, PkgType type) : type_(type), pkgStream_(stream) {} + PkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream, PkgType type) + : type_(type), pkgStream_(stream), pkgManager_(manager) {} virtual ~PkgFile(); @@ -136,6 +137,7 @@ protected: PkgType type_ {}; PkgStreamPtr pkgStream_ = nullptr; + PkgManager::PkgManagerPtr pkgManager_ = nullptr; uint32_t nodeId_ = 0; std::map pkgEntryMapId_ {}; std::multimap> pkgEntryMapFileName_ {}; diff --git a/services/package/pkg_package/pkg_upgradefile.cpp b/services/package/pkg_package/pkg_upgradefile.cpp index 8ca023789c11635bc8fa437ffa3bc431aa68b018..ecda48ae12f5b262a0db716df72bccbdf39c3581 100644 --- a/services/package/pkg_package/pkg_upgradefile.cpp +++ b/services/package/pkg_package/pkg_upgradefile.cpp @@ -129,10 +129,10 @@ int32_t UpgradePkgFile::SavePackage(size_t &signOffset) WriteLE32(reinterpret_cast(&header->updateFileVersion), pkgInfo_.updateFileVersion); int32_t ret = memcpy_s(header->softwareVersion, sizeof(header->softwareVersion), pkgInfo_.softwareVersion.data(), pkgInfo_.softwareVersion.size()); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret); ret = memcpy_s(header->productUpdateId, sizeof(header->productUpdateId), pkgInfo_.productUpdateId.data(), pkgInfo_.productUpdateId.size()); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret); offset += sizeof(UpgradePkgHeader); // 时间tlv WriteLE16(buffer.data() + offset, 0x02); // Type is 2 for time in TLV format @@ -140,16 +140,16 @@ int32_t UpgradePkgFile::SavePackage(size_t &signOffset) offset += sizeof(PkgTlv); UpgradePkgTime *time = reinterpret_cast(buffer.data() + offset); ret = memcpy_s(time->date, sizeof(time->date), pkgInfo_.date.data(), pkgInfo_.date.size()); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret); ret = memcpy_s(time->time, sizeof(time->time), pkgInfo_.time.data(), pkgInfo_.time.size()); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret:%d", pkgStream_->GetFileName().c_str(), ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s %s ret: %d", pkgStream_->GetFileName().c_str(), ret); offset += sizeof(UpgradePkgTime); // 组件的tlv WriteLE16(buffer.data() + offset, 0x05); // Type is 5 for component in TLV format WriteLE16(buffer.data() + offset + sizeof(uint16_t), pkgInfo_.pkgInfo.entryCount * sizeof(UpgradeCompInfo)); offset += sizeof(PkgTlv); ret = pkgStream_->Write(buffer, UPGRADE_FILE_HEADER_LEN, 0); - PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write upgrade file header for %s ret:%d", + PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail write upgrade file header for %s ret: %d", pkgStream_->GetFileName().c_str(), ret); // Clear buffer and save signature information @@ -233,6 +233,7 @@ int32_t UpgradePkgFile::Verify(size_t start, DigestAlgorithm::DigestAlgorithmPtr ret = pkgStream_->Read(buffer, offset, remainBytes, readBytes); PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail to read data "); algorithm->Update(buffer, readBytes); + pkgManager_->PostDecodeProgress(POST_TYPE_VERIFY_PKG, remainBytes, nullptr); } PkgBuffer digest(GetDigestLen()); @@ -325,6 +326,11 @@ int32_t UpgradePkgFile::ReadUpgradePkgHeader(const PkgBuffer &buffer, size_t &re PkgFile::ConvertBufferToString(pkgInfo_.productUpdateId, {header->productUpdateId, sizeof(header->productUpdateId)}); + algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(pkgInfo_.pkgInfo.digestMethod); + PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, + "Invalid file %s", pkgStream_->GetFileName().c_str()); + algorithm->Init(); + if (currLen + tlv.length >= readLen) { // Extra TLV information, read it. realLen = currLen + tlv.length; algorithm->Update(buffer, realLen); @@ -347,10 +353,6 @@ int32_t UpgradePkgFile::ReadUpgradePkgHeader(const PkgBuffer &buffer, size_t &re realLen += currLen; // Parser header to get compressional algorithm - algorithm = PkgAlgorithmFactory::GetDigestAlgorithm(pkgInfo_.pkgInfo.digestMethod); - PKG_CHECK(algorithm != nullptr, return PKG_NOT_EXIST_ALGORITHM, - "Invalid file %s", pkgStream_->GetFileName().c_str()); - algorithm->Init(); algorithm->Update(buffer, currLen); // Generate digest return PKG_SUCCESS; } @@ -372,7 +374,7 @@ int32_t UpgradeFileEntry::EncodeHeader(PkgStreamPtr inStream, size_t startOffset PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_PARAM, "outStream or inStream null for %s", fileName_.c_str()); ret = memcpy_s(comp.digest, sizeof(comp.digest), fileInfo_.digest, sizeof(fileInfo_.digest)); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret: %d", ret); WriteLE32(reinterpret_cast(&comp.size), fileInfo_.fileInfo.unpackedSize); WriteLE16(reinterpret_cast(&comp.id), fileInfo_.id); WriteLE32(reinterpret_cast(&comp.originalSize), fileInfo_.originalSize); @@ -434,7 +436,7 @@ int32_t UpgradeFileEntry::DecodeHeader(const PkgBuffer &buffer, size_t headerOff fileInfo_.fileInfo.packMethod = PKG_COMPRESS_METHOD_NONE; fileInfo_.fileInfo.digestMethod = PKG_DIGEST_TYPE_NONE; int32_t ret = memcpy_s(fileInfo_.digest, sizeof(fileInfo_.digest), info->digest, sizeof(info->digest)); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret: %d", ret); PkgFile::ConvertBufferToString(fileInfo_.fileInfo.identity, {info->address, sizeof(info->address)}); PkgFile::ConvertBufferToString(fileInfo_.version, {info->version, sizeof(info->version)}); fileName_ = fileInfo_.fileInfo.identity; @@ -466,7 +468,7 @@ int32_t UpgradeFileEntry::Unpack(PkgStreamPtr outStream) 0, fileInfo_.fileInfo.digestMethod }; int32_t ret = memcpy_s(context.digest, sizeof(context.digest), fileInfo_.digest, sizeof(fileInfo_.digest)); - PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret:%d", ret); + PKG_CHECK(ret == EOK, return ret, "Fail to memcpy_s ret: %d", ret); ret = algorithm->Unpack(inStream, outStream, context); PKG_CHECK(ret == PKG_SUCCESS, return ret, "Fail Decompress for %s", fileName_.c_str()); PKG_LOGI("Unpack %s data offset:%zu packedSize:%zu unpackedSize:%zu", fileName_.c_str(), dataOffset_, diff --git a/services/package/pkg_package/pkg_upgradefile.h b/services/package/pkg_package/pkg_upgradefile.h index 93a8ec6135dd436b99fb7b5fbfc51cf18298f8d4..e2fdbb273c6f068aa788f1ec24019713143c15b7 100644 --- a/services/package/pkg_package/pkg_upgradefile.h +++ b/services/package/pkg_package/pkg_upgradefile.h @@ -78,8 +78,8 @@ private: class UpgradePkgFile : public PkgFile { public: - UpgradePkgFile(PkgStreamPtr stream, PkgManager::PkgInfoPtr header) : - PkgFile(stream, PkgFile::PKG_TYPE_UPGRADE) + UpgradePkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream, PkgManager::PkgInfoPtr header) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_UPGRADE) { if (header == nullptr || header->entryCount == 0) { return; @@ -92,7 +92,7 @@ public: int32_t AddEntry(const PkgManager::FileInfoPtr file, const PkgStreamPtr input) override; - int32_t SavePackage(size_t &offset) override; + int32_t SavePackage(size_t &signOffset) override; int32_t LoadPackage(std::vector &fileNames, VerifyFunction verify = nullptr) override; diff --git a/services/package/pkg_package/pkg_zipfile.cpp b/services/package/pkg_package/pkg_zipfile.cpp index 5ea2eb6b2ae033764c93e7e0fefcecbc32ee557e..df5626c44a7322c1c3c1cf1b33719c155d9e47f8 100644 --- a/services/package/pkg_package/pkg_zipfile.cpp +++ b/services/package/pkg_package/pkg_zipfile.cpp @@ -109,7 +109,7 @@ int32_t ZipPkgFile::LoadPackage(std::vector &fileNames, const PkgBu (endDir.startDiskOfCentralDir != 0) #ifndef UPDATER_UT || (endDir.offset >= fileLen) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) || - (endDir.commentLen = 0) || ((endDir.offset + endDir.sizeOfCentralDir + endDirLen) > fileLen) + ((endDir.offset + endDir.sizeOfCentralDir + endDirLen) > fileLen) #endif ) { PKG_LOGE("end dir format error %s", pkgStream_->GetFileName().c_str()); diff --git a/services/package/pkg_package/pkg_zipfile.h b/services/package/pkg_package/pkg_zipfile.h index 01ef177e2d6b62af38ce490ac184706f433a783b..706e57154bf942fae67d8162280166fe548b461e 100644 --- a/services/package/pkg_package/pkg_zipfile.h +++ b/services/package/pkg_package/pkg_zipfile.h @@ -168,7 +168,8 @@ private: class ZipPkgFile : public PkgFile { public: - explicit ZipPkgFile(PkgStreamPtr stream) : PkgFile(stream, PkgFile::PKG_TYPE_ZIP) + explicit ZipPkgFile(PkgManager::PkgManagerPtr manager, PkgStreamPtr stream) + : PkgFile(manager, stream, PkgFile::PKG_TYPE_ZIP) { pkgInfo_.signMethod = PKG_SIGN_METHOD_RSA; pkgInfo_.digestMethod = PKG_DIGEST_TYPE_SHA256; diff --git a/services/script/BUILD.gn b/services/script/BUILD.gn index 641fe9eadf629d2467e8bdc76a8a467f58f5bb58..41ddffafa9871e602a4b60ff2f778697a115680c 100644 --- a/services/script/BUILD.gn +++ b/services/script/BUILD.gn @@ -66,4 +66,7 @@ ohos_static_library("libupdaterscript") { "//third_party/bounds_checking_function:libsec_static", "//utils/native/base:utils", ] + + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/script/script_interpreter/script_expression.cpp b/services/script/script_interpreter/script_expression.cpp index d3f6293b8575882990c543fb41f9d9808d5c10cf..048d1b38644e12913d2b3a509827327b422ef3eb 100644 --- a/services/script/script_interpreter/script_expression.cpp +++ b/services/script/script_interpreter/script_expression.cpp @@ -154,16 +154,7 @@ UScriptValuePtr FunctionCallExpression::Execute(ScriptInterpreter &inter, UScrip if (inter.IsNativeFunction(functionName_)) { return inter.ExecuteNativeFunc(local, functionName_, params_); } - - ScriptFunction* function = function_; - if (function_ == nullptr) { - function = inter.FindFunction(functionName_); - } - if (function == nullptr) { - INTERPRETER_LOGI(inter, local, "Can not find function %s", functionName_.c_str()); - return std::make_shared(USCRIPT_NOTEXIST_INSTRUCTION); - } - return function->Execute(inter, local, params_); + return inter.ExecuteFunction(local, functionName_, params_); } BinaryExpression::~BinaryExpression() @@ -177,7 +168,6 @@ AssignExpression::~AssignExpression() } FunctionCallExpression::~FunctionCallExpression() { - delete function_; delete params_; } } // namespace uscript diff --git a/services/script/script_interpreter/script_expression.h b/services/script/script_interpreter/script_expression.h index c864969c5ac108d12aa428dd8932dc3b0022b12d..1d4e163f0315ce559368003020cb1aa044896d15 100644 --- a/services/script/script_interpreter/script_expression.h +++ b/services/script/script_interpreter/script_expression.h @@ -200,7 +200,6 @@ public: static UScriptExpression* CreateExpression(std::string identifier, ScriptParams *params); private: std::string functionName_; - ScriptFunction* function_ = nullptr; ScriptParams* params_ = nullptr; }; } // namespace uscript diff --git a/services/script/script_interpreter/script_interpreter.cpp b/services/script/script_interpreter/script_interpreter.cpp index bef46fa8a23e90e803b7a2e6223b36c3dc6bca28..0531a914aa55d4d4b57904a2f8de52e8f3b6e255 100644 --- a/services/script/script_interpreter/script_interpreter.cpp +++ b/services/script/script_interpreter/script_interpreter.cpp @@ -109,6 +109,18 @@ ScriptFunction* ScriptInterpreter::FindFunction(const std::string &name) return nullptr; } +UScriptValuePtr ScriptInterpreter::ExecuteFunction(UScriptContextPtr context, const std::string &name, + ScriptParams *params) +{ + ScriptFunction *function = FindFunction(name); + if (function == nullptr) { + USCRIPT_LOGI("Fail to find function %s", name.c_str()); + return std::make_shared(USCRIPT_NOTEXIST_INSTRUCTION); + } else { + return function->Execute(*this, context, params); + } +} + UScriptValuePtr ScriptInterpreter::FindVariable(UScriptContextPtr local, std::string id) { for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) { diff --git a/services/script/script_interpreter/script_interpreter.h b/services/script/script_interpreter/script_interpreter.h index 7a30b0a1058bc1f3cd7d0b49109eee5f360c79bf..adced81b722bfad2a376c37dc0297a20a54f6a5c 100644 --- a/services/script/script_interpreter/script_interpreter.h +++ b/services/script/script_interpreter/script_interpreter.h @@ -49,10 +49,11 @@ public: void AddStatement(UScriptStatement *statement); int32_t AddFunction(ScriptFunction *function); - ScriptFunction* FindFunction(const std::string &name); bool IsNativeFunction(std::string name); UScriptValuePtr ExecuteNativeFunc(UScriptContextPtr upContext, const std::string &name, ScriptParams *params); + UScriptValuePtr ExecuteFunction(UScriptContextPtr context, const std::string &name, + ScriptParams *params); UScriptValuePtr FindVariable(UScriptContextPtr local, std::string id); UScriptValuePtr UpdateVariable(UScriptContextPtr local, std::string id, UScriptValuePtr var); int32_t GetInstanceId() const @@ -74,6 +75,7 @@ private: int32_t Execute(); private: + ScriptFunction* FindFunction(const std::string &name); UScriptStatementList* statements_ = nullptr; std::map functions_; std::vector contextStack_; @@ -83,4 +85,4 @@ private: int32_t instanceId_ = 0; }; } // namespace uscript -#endif \ No newline at end of file +#endif diff --git a/services/ui/BUILD.gn b/services/ui/BUILD.gn index edab2abd0f5fc712c97419885cfb0b13ca053c44..760019c030b028c862319fc561391129160deca3 100644 --- a/services/ui/BUILD.gn +++ b/services/ui/BUILD.gn @@ -55,4 +55,7 @@ ohos_static_library("libui") { "//third_party/libdrm:libdrm", "//third_party/libpng:libpng", ] + + subsystem_name = "updater" + part_name = "updater" } diff --git a/services/ui/drm_driver.cpp b/services/ui/drm_driver.cpp index 648719ac7ac2e2a5e3f16a422bdfaaaa19e7c468..44a5ae01564202329db835ce8b07bca6494b003b 100644 --- a/services/ui/drm_driver.cpp +++ b/services/ui/drm_driver.cpp @@ -19,7 +19,7 @@ #include "securec.h" namespace updater { -void DrmDriver::FlipBuffer(void *buf) +void DrmDriver::FlipBuffer(const void *buf) { if (!buf) { LOG(ERROR) << "buf is null"; @@ -72,32 +72,204 @@ int DrmDriver::ModesetCreateFb(struct BufferObject *bo) return 0; } +drmModeCrtc *DrmDriver::GetCrtc(const drmModeRes &res, const int fd, const drmModeConnector &conn) const +{ + // if connector has one encoder, use it + drmModeEncoder *encoder = nullptr; + if (conn.encoder_id != 0) { + encoder = drmModeGetEncoder(fd, conn.encoder_id); + } + if (encoder != nullptr && encoder->crtc_id != 0) { + uint32_t crtcId = encoder->crtc_id; + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, crtcId); + } + + if (encoder != nullptr) { + drmModeFreeEncoder(encoder); + } + + // try get a vaild encoder and crtc + for (int i = 0; i < conn.count_encoders; i++) { + encoder = drmModeGetEncoder(fd, conn.encoders[i]); + if (encoder == nullptr) { + continue; + } + + for (int j = 0; j < res.count_crtcs; j++) { + if ((encoder->possible_crtcs & (1u << static_cast(j))) != 0) { + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, res.crtcs[j]); + } + } + drmModeFreeEncoder(encoder); + } + return nullptr; +} + +drmModeConnector *DrmDriver::GetFirstConnector(const drmModeRes &res, const int fd) const +{ + // get connected connector + for (int i = 0; i < res.count_connectors; i++) { + drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]); + if (conn == nullptr) { + continue; + } + if (conn->count_modes > 0 && + conn->connection == DRM_MODE_CONNECTED) { + return conn; + } + drmModeFreeConnector(conn); + } + return nullptr; +} + +drmModeConnector *DrmDriver::GetConnectorByType(const drmModeRes &res, const int fd, const uint32_t type) const +{ + // get connected connector + for (int i = 0; i < res.count_connectors; i++) { + drmModeConnector *conn = drmModeGetConnector(fd, res.connectors[i]); + if (conn == nullptr) { + continue; + } + if (conn->connector_type == type && + conn->count_modes > 0 && + conn->connection == DRM_MODE_CONNECTED) { + return conn; + } + drmModeFreeConnector(conn); + } + return nullptr; +} + + +drmModeConnector *DrmDriver::GetConnector(const drmModeRes &res, const int fd, uint32_t &modeId) const +{ + // get main connector : lvds edp and dsi + uint32_t mainConnector[] = { + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_DSI, + }; + + drmModeConnector *conn = nullptr; + for (uint32_t i = 0; i < sizeof(mainConnector) / sizeof(mainConnector[0]); i++) { + conn = GetConnectorByType(res, fd, mainConnector[i]); + if (conn != nullptr) { + break; + } + } + + if (conn == nullptr) { + conn = GetFirstConnector(res, fd); + } + + if (conn == nullptr) { + LOG(ERROR) << "DrmDriver cannot get vaild connector"; + return nullptr; + } + + // get preferred mode index + modeId = 0; + for (int i = 0; i < conn->count_modes; i++) { + if ((conn->modes[i].type & DRM_MODE_TYPE_PREFERRED) != 0) { + modeId = i; + break; + } + } + + return conn; +} + +drmModeRes *DrmDriver::GetResources(int &fd) const +{ + // 1: open drm resource + drmModeRes *res = nullptr; + for (int i = 0; i < DRM_MAX_MINOR; i++) { + res = GetOneResources(i, fd); + if (res != nullptr) { + break; + } + } + return res; +} + +drmModeRes *DrmDriver::GetOneResources(const int devIndex, int &fd) const +{ + // 1: open drm device + fd = -1; + std::string devName = std::string("/dev/dri/card") + std::to_string(devIndex); + int tmpFd = open(devName.c_str(), O_RDWR | O_CLOEXEC); + if (tmpFd < 0) { + LOG(ERROR) << "open failed " << devName; + return nullptr; + } + // 2: check drm capacity + uint64_t cap = 0; + int ret = drmGetCap(tmpFd, DRM_CAP_DUMB_BUFFER, &cap); + if (ret != 0 || cap == 0) { + LOG(ERROR) << "drmGetCap failed"; + close(tmpFd); + return nullptr; + } + + // 3: get drm resources + drmModeRes *res = drmModeGetResources(tmpFd); + if (res == nullptr) { + LOG(ERROR) << "drmModeGetResources failed"; + close(tmpFd); + return nullptr; + } + + // 4: check it has connected connector and crtc + if (res->count_crtcs > 0 && res->count_connectors > 0 && res->count_encoders > 0) { + drmModeConnector *conn = GetFirstConnector(*res, tmpFd); + if (conn != nullptr) { + // don't close fd + LOG(INFO) << "drm dev:" << devName; + drmModeFreeConnector(conn); + fd = tmpFd; + return res; + } + } + close(tmpFd); + drmModeFreeResources(res); + return nullptr; +} + int DrmDriver::DrmInit(void) { - fd_ = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); - if (fd_ < 0) { - LOG(ERROR) << "open failed"; + // 1: open drm resource + res_ = GetResources(fd_); + if (fd_ < 0 || res_ == nullptr) { + LOG(ERROR) << "DrmInit: GetResources failed"; return -1; } - res_ = drmModeGetResources(fd_); - if (res_ == nullptr) { - LOG(ERROR) << "drmModeGetResources"; + // 2 : get connected connector + uint32_t modeId; + conn_ = GetConnector(*res_, fd_, modeId); + if (conn_ == nullptr) { + LOG(ERROR) << "DrmInit: GetConnector failed"; return -1; } - uint32_t crtcId = res_->crtcs[0]; - uint32_t connId = res_->connectors[1]; - conn_ = drmModeGetConnector(fd_, connId); - if (conn_ == nullptr) { - LOG(ERROR) << "drmModeGetConnector"; + // 3: get vaild encoder and crtc + crtc_ = GetCrtc(*res_, fd_, *conn_); + if (crtc_ == nullptr) { + LOG(ERROR) << "DrmInit: GetCrtc failed"; return -1; } - buff_.width = conn_->modes[0].hdisplay; - buff_.height = conn_->modes[0].vdisplay; + // 4: create userspace buffer + buff_.width = conn_->modes[modeId].hdisplay; + buff_.height = conn_->modes[modeId].vdisplay; ModesetCreateFb(&buff_); - drmModeSetCrtc(fd_, crtcId, buff_.fbId, 0, 0, &connId, 1, &conn_->modes[0]); + + // 5: bind ctrc and connector + drmModeSetCrtc(fd_, crtc_->crtc_id, buff_.fbId, 0, 0, &conn_->connector_id, 1, &conn_->modes[modeId]); + LOG(INFO) << "DrmInit: buff_.width:" << buff_.width << " buff_.height:" << buff_.height; + LOG(INFO) << "DrmInit: crtc_id:" << crtc_->crtc_id << " connector_id:" << conn_->connector_id; LOG(INFO) << " drm init success."; return 0; } @@ -111,14 +283,29 @@ void DrmDriver::LoadDrmDriver() void DrmDriver::ModesetDestroyFb(struct BufferObject *bo) { - struct drm_mode_destroy_dumb destroy = {}; - drmModeRmFB(fd_, bo->fbId); - munmap(bo->vaddr, bo->size); - destroy.handle = bo->handle; - drmIoctl(fd_, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy); - drmModeFreeConnector(conn_); - drmModeFreeResources(res_); - close(fd_); + if (fd_ > 0 && bo->fbId != 0) { + drmModeRmFB(fd_, bo->fbId); + } + if (bo->vaddr != nullptr) { + munmap(bo->vaddr, bo->size); + } + if (fd_ > 0) { + struct drm_mode_destroy_dumb destroy = {}; + destroy.handle = bo->handle; + drmIoctl(fd_, DRM_IOCTL_GEM_CLOSE, &destroy); + } + if (crtc_ != nullptr) { + drmModeFreeCrtc(crtc_); + } + if (conn_ != nullptr) { + drmModeFreeConnector(conn_); + } + if (res_ != nullptr) { + drmModeFreeResources(res_); + } + if (fd_ > 0) { + close(fd_); + } } DrmDriver::~DrmDriver() diff --git a/services/ui/drm_driver.h b/services/ui/drm_driver.h index 62b5385f20d2e1c46cd937ee40352b6278025348..2d10391f3dcb514802ca8eaa623c2b19bf881e6e 100644 --- a/services/ui/drm_driver.h +++ b/services/ui/drm_driver.h @@ -40,18 +40,25 @@ struct BufferObject { class DrmDriver { protected: - DrmDriver() : fd_(-1), conn_(nullptr), res_(nullptr) {} + DrmDriver() : fd_(-1), conn_(nullptr), res_(nullptr), crtc_(nullptr) {} virtual ~DrmDriver(); - void FlipBuffer(void* buf); + void FlipBuffer(const void* buf); void LoadDrmDriver(); private: int ModesetCreateFb(struct BufferObject *bo); void ModesetDestroyFb(struct BufferObject *bo); int DrmInit(); + drmModeCrtc *GetCrtc(const drmModeRes &res, const int fd, const drmModeConnector &conn) const; + drmModeConnector *GetFirstConnector(const drmModeRes &res, const int fd) const; + drmModeConnector *GetConnectorByType(const drmModeRes &res, const int fd, const uint32_t type) const; + drmModeConnector *GetConnector(const drmModeRes &res, const int fd, uint32_t &modeId) const; + drmModeRes *GetResources(int &fd) const; + drmModeRes *GetOneResources(const int devIndex, int &fd) const; int fd_; drmModeConnector *conn_; drmModeRes *res_; - struct BufferObject buff_; + drmModeCrtc *crtc_; + struct BufferObject buff_ {}; }; } // namespace updater #endif diff --git a/services/ui/progress_bar.cpp b/services/ui/progress_bar.cpp index 37109d840f4116732626f98a6af706b5ddafc16a..d3df1185489046e15522ec391f1f13aa89676d78 100644 --- a/services/ui/progress_bar.cpp +++ b/services/ui/progress_bar.cpp @@ -20,27 +20,27 @@ #include "securec.h" namespace updater { -constexpr int DEFAULT_PROGRESS_COLOR_A = 0xCC; constexpr int DEFAULT_NORMAL_COLOR = 0xFF; constexpr int MAX_PROGRESS_VALUE = 100; constexpr uint32_t DEFAULT_PROGRESS_COLOR = 0x00; -ProgressBar::ProgressBar(const int mStartX, const int mStartY, const int w, const int h, Frame *mParent) +ProgressBar::ProgressBar(const int startX, const int startY, const int w, const int h, Frame *parent) { - startX_ = mStartX; - startY_ = mStartY; + startX_ = startX; + startY_ = startY; this->CreateBuffer(w, h, View::PixelFormat::BGRA888); - parent_ = mParent; + parent_ = parent; SetFocusAble(false); parent_->ViewRegister(this); progressColor_.r = DEFAULT_NORMAL_COLOR; progressColor_.g = DEFAULT_NORMAL_COLOR; progressColor_.b = DEFAULT_NORMAL_COLOR; progressColor_.a = DEFAULT_NORMAL_COLOR; - normalColor_.r = DEFAULT_PROGRESS_COLOR; + normalColor_.r = DEFAULT_NORMAL_COLOR; normalColor_.g = DEFAULT_PROGRESS_COLOR; normalColor_.b = DEFAULT_PROGRESS_COLOR; - normalColor_.a = DEFAULT_PROGRESS_COLOR_A; + normalColor_.a = DEFAULT_NORMAL_COLOR; + DrawBackground(); } void ProgressBar::SetProgressValue(int value) @@ -82,6 +82,7 @@ void ProgressBar::DrawProgress() void ProgressBar::OnDraw() { SyncBuffer(); + DrawBackground(); DrawProgress(); if (parent_ != nullptr) { parent_->OnDraw(); @@ -90,4 +91,23 @@ void ProgressBar::OnDraw() } return; } -} // namespace updater \ No newline at end of file + +void ProgressBar::DrawBackground() +{ + int ret = 0; + char *tmpBuf = static_cast(GetBuffer()); + BRGA888Pixel pixBuf[viewWidth_]; + for (int a = 0; a < viewWidth_; a++) { + pixBuf[a].r = normalColor_.r; + pixBuf[a].g = normalColor_.g; + pixBuf[a].b = normalColor_.b; + pixBuf[a].a = normalColor_.a; + } + for (int i = 0; i < viewHeight_; i++) { + ret = memcpy_s(tmpBuf + i * viewWidth_ * sizeof(BRGA888Pixel), viewWidth_ * sizeof(BRGA888Pixel) + 1, + reinterpret_cast(pixBuf), viewWidth_ * sizeof(BRGA888Pixel)); + UPDATER_ERROR_CHECK(ret == 0, "memcpy_s error", break); + } + return; +} +} // namespace updater diff --git a/services/ui/progress_bar.h b/services/ui/progress_bar.h index 100139718ed003cf0f2c1884d53078a6eed2ebc4..e0edd9e7cd04e6f7b9e083187d3d987e885614d7 100644 --- a/services/ui/progress_bar.h +++ b/services/ui/progress_bar.h @@ -27,6 +27,7 @@ public: void SetProgressValue(int value); private: void DrawProgress(); + void DrawBackground(); BRGA888Pixel progressColor_ {}; BRGA888Pixel normalColor_ {}; int pValue_ { 0 }; diff --git a/services/ui/surface_dev.cpp b/services/ui/surface_dev.cpp index 73de0f69f16fb5f9de6cb6cff153b2c101b52cdc..fbfb53c0178bbabefbfefce6b825997e390f8b6a 100644 --- a/services/ui/surface_dev.cpp +++ b/services/ui/surface_dev.cpp @@ -17,7 +17,7 @@ #include "updater_ui_const.h" namespace updater { -void SurfaceDev::Flip(void *buf) +void SurfaceDev::Flip(const void *buf) { if (!buf) { LOG(ERROR) << "buf is null"; diff --git a/services/ui/surface_dev.h b/services/ui/surface_dev.h index cc7c47ac098eb65bbf91720568e499c9e7372cc0..d65d1a654e5cdcb43147af1740466782356614a8 100644 --- a/services/ui/surface_dev.h +++ b/services/ui/surface_dev.h @@ -25,9 +25,9 @@ public: DRM_DEVICE, }; - explicit SurfaceDev(SurfaceDev::DevType deviceType); + explicit SurfaceDev(SurfaceDev::DevType devType); ~SurfaceDev() override; - void Flip(void* buf); + void Flip(const void* buf); void GetScreenSize(int &w, int &h); private: int screenSizeW_ = 0; diff --git a/services/ui/text_label.cpp b/services/ui/text_label.cpp index 0b87320efa3ef56d6de6111871c1debdf25d2f36..6037f3e17376a1f9984d6d7936a37a016055bb30 100644 --- a/services/ui/text_label.cpp +++ b/services/ui/text_label.cpp @@ -37,7 +37,6 @@ TextLabel::TextLabel(int mStartX, int mStartY, int w, int h, Frame *mparent) outlineColor_.b = 0x00; outlineColor_.a = 0x00; boldTopLine_ = false; - boldTopLine_ = false; const char midAlpha = 0xAA; actionBgColor_.r = 0x00; @@ -78,6 +77,15 @@ static void PngInitSet(png_structp fontPngPtr, FILE *fp, int size, png_infop fon return; } +static void CheckInitFont(png_structp fontPngPtr, FILE *fp, png_infop fontInfoPtr) +{ + png_destroy_read_struct(&fontPngPtr, &fontInfoPtr, 0); + if (fp != nullptr) { + fclose(fp); + fp = nullptr; + } +} + static void PNGReadRow(png_uint_32 fontWidth, png_uint_32 fontHeight, png_structp fontPngPtr, char *fontBuf) { if ((fontWidth > MAX_FONT_BUFFER_SIZE_HW) || (fontHeight > MAX_FONT_BUFFER_SIZE_HW)) { @@ -97,12 +105,10 @@ void TextLabel::InitFont() png_infop fontInfoPtr = nullptr; png_uint_32 fontWidth = 0; png_uint_32 fontHeight = 0; - png_byte fontChannels = 0; png_structp fontPngPtr = nullptr; int fontBitDepth = 0; int fontColorType = 0; - uint32_t offset = 2; - UPDATER_CHECK_ONLY_RETURN(!memset_s(resPath, MAX_TEXT_SIZE + offset, 0, MAX_TEXT_SIZE + 1), return); + UPDATER_CHECK_ONLY_RETURN(!memset_s(resPath, MAX_TEXT_SIZE + offset_, 0, MAX_TEXT_SIZE + 1), return); switch (fontType_) { case DEFAULT_FONT: UPDATER_CHECK_ONLY_RETURN(snprintf_s(resPath, sizeof(resPath), sizeof(resPath) -1, "/resources/%s.png", @@ -115,8 +121,7 @@ void TextLabel::InitFont() } FILE* fp = fopen(resPath, "rb"); UPDATER_ERROR_CHECK(fp, "open font failed!", return); - const int headerNumber = 8; - uint8_t header[headerNumber]; + uint8_t header[headerNumber_]; size_t bytesRead = fread(header, 1, sizeof(header), fp); UPDATER_ERROR_CHECK(bytesRead == sizeof(header), "read header failed!", fclose(fp); return); if (png_sig_cmp(header, 0, sizeof(header))) { @@ -128,21 +133,21 @@ void TextLabel::InitFont() UPDATER_ERROR_CHECK(fontPngPtr, "creat font ptr_ failed!", fclose(fp); return); fontInfoPtr = png_create_info_struct(fontPngPtr); if (fontInfoPtr == nullptr) { + png_destroy_read_struct(&fontPngPtr, nullptr, nullptr); fclose(fp); return; } PngInitSet(fontPngPtr, fp, sizeof(header), fontInfoPtr); png_get_IHDR(fontPngPtr, fontInfoPtr, &fontWidth, &fontHeight, &fontBitDepth, &fontColorType, nullptr, nullptr, nullptr); - fontChannels = png_get_channels(fontPngPtr, fontInfoPtr); - const int defaultFontBitDepth = 8; - if (fontBitDepth <= defaultFontBitDepth && fontChannels == 1 && fontColorType == PNG_COLOR_TYPE_GRAY) { + png_byte fontChannels = png_get_channels(fontPngPtr, fontInfoPtr); + if (fontBitDepth <= defaultFontBitDepth_ && fontChannels == 1 && fontColorType == PNG_COLOR_TYPE_GRAY) { png_set_expand_gray_1_2_4_to_8(fontPngPtr); } - const int defaultFontWidth = 96; - fontWidth_ = fontWidth / defaultFontWidth; + fontWidth_ = fontWidth / defaultFontWidth_; fontHeight_ = fontHeight >> 1; PNGReadRow(fontWidth_, fontHeight_, fontPngPtr, fontBuf_); + CheckInitFont(fontPngPtr, fp, fontInfoPtr); } void TextLabel::SetText(const char *str) diff --git a/services/ui/text_label.h b/services/ui/text_label.h index 39f4d1b2000935c08b18b73745e0a92c2021d77b..82d5fb9a4cb04df8b185a9b72630701f817487c9 100644 --- a/services/ui/text_label.h +++ b/services/ui/text_label.h @@ -75,6 +75,10 @@ private: char fontBuf_[MAX_FONT_BUFFER_SIZE_HW * FONT_BUFFER_SIZE] {}; unsigned int fontWidth_ = 0; unsigned int fontHeight_ = 0; + uint32_t offset_ = 2; + const int defaultFontWidth_ = 96; + const int defaultFontBitDepth_ = 8; + const int headerNumber_ = 8; }; } // namespace updater #endif diff --git a/services/ui/updater_ui.cpp b/services/ui/updater_ui.cpp index a69029374b812bff5cfa989dd0ac570539958c43..edcbc93cfad0d70c7d6fdc1b8a76a62b76772565 100644 --- a/services/ui/updater_ui.cpp +++ b/services/ui/updater_ui.cpp @@ -33,7 +33,6 @@ constexpr int LABEL_HEIGHT = 13; constexpr int MAX_IMGS = 62; constexpr int DIALIG_COLOR_A = 0xAA; constexpr int DIALOG_COLOR = 0x00; -constexpr int DISPLAY_TIME = 1000 * 1000; int g_updateFlag = 0; int g_textLabelNum = 0; @@ -163,21 +162,19 @@ 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(); } else if (viewId == g_textLabel3->GetViewId() && g_textLabel3->IsVisiable()) { HideDialog(); - g_logLabel->SetText("Don't remove SD Card!"); - usleep(DISPLAY_TIME); UpdaterStatus status = UpdaterFromSdcard(); if (status != UPDATE_SUCCESS) { ShowUpdateFrame(false); ShowMenu(); return; } - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); } else if (viewId == g_dialogCancalBtn->GetViewId() && g_dialogCancalBtn->IsVisiable()) { HideDialog(); @@ -442,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); @@ -521,4 +519,19 @@ void DeleteView() g_sfDev = nullptr; } } -} // namespace updater \ No newline at end of file + +TextLabel *GetUpdateInfoLabel() +{ + return g_updateInfoLabel; +} + +ProgressBar *GetProgressBar() +{ + return g_progressBar; +} + +void SetUpdateFlag(int updateFlag) +{ + g_updateFlag = updateFlag; +} +} // namespace updater diff --git a/services/ui/updater_ui.h b/services/ui/updater_ui.h index d495aa16388e92b7852758a7a21570412ec3d01c..621df1c38921286d487430e07445f03610fa7612 100644 --- a/services/ui/updater_ui.h +++ b/services/ui/updater_ui.h @@ -17,6 +17,7 @@ #include #include "text_label.h" +#include "progress_bar.h" namespace updater { void DoProgress(); @@ -28,5 +29,11 @@ void UpdaterUiInit(); void ShowText(TextLabel *label, std::string text); void DeleteView(); + +TextLabel *GetUpdateInfoLabel(); + +ProgressBar *GetProgressBar(); + +void SetUpdateFlag(int updateFlag); } // namespace updater #endif /* UPDATE_UI_HOS_UPDATER_H */ diff --git a/services/ui/view.h b/services/ui/view.h index afde4bd484bb18afa1275e1d659d3f6daf4db657..0f8fa7e00522f0bccb7567e1685dff747fb69319 100644 --- a/services/ui/view.h +++ b/services/ui/view.h @@ -70,9 +70,9 @@ public: std::mutex mutex_; protected: void* CreateBuffer(int w, int h, int pixelFormat); -private: char* viewBuffer_ = nullptr; char* shadowBuffer_ = nullptr; +private: int bufferSize_ = 0; bool isVisiable_ = true; int viewId_ = 0; diff --git a/services/updater.cpp b/services/updater.cpp index 43fb6b6fc99d53782bc9c787a6a63e71d049fa59..3aa34d7466ef35e69d5b6d67960fefc21e64c5fe 100644 --- a/services/updater.cpp +++ b/services/updater.cpp @@ -42,9 +42,6 @@ using updater::utils::SplitString; using updater::utils::Trim; using namespace hpackage; -extern TextLabel *g_updateInfoLabel; -extern ProgressBar *g_progressBar; - int g_percentage; int g_tmpProgressValue; int g_tmpValue; @@ -116,43 +113,7 @@ int UpdatePreProcess(PkgManager::PkgManagerPtr pkgManager, const std::string &pa return ret; } -static UpdaterStatus IsSpaceCapacitySufficient(const std::string &packagePath) -{ - PkgManager::PkgManagerPtr pkgManager = hpackage::PkgManager::CreatePackageInstance(); - UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT); - std::vector fileIds; - int ret = pkgManager->LoadPackageWithoutUnPack(packagePath, fileIds); - UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "LoadPackageWithoutUnPack failed", return UPDATE_CORRUPT); - - const FileInfo *info = pkgManager->GetFileInfo("update.bin"); - UPDATER_ERROR_CHECK(info != nullptr, "update.bin is not exist", return UPDATE_CORRUPT); - - PkgManager::ReleasePackageInstance(pkgManager); - - struct statvfs64 updaterVfs; - if (access("/sdcard/updater", 0) == 0) { - struct statvfs64 dataVfs {}; - UPDATER_ERROR_CHECK(statvfs64("/data", &dataVfs) >= 0, "Statvfs read /data error!", return UPDATE_ERROR); - UPDATER_ERROR_CHECK(dataVfs.f_bfree * dataVfs.f_bsize > MAX_LOG_SPACE, "/data free space is not enough", - return UPDATE_ERROR); - - UPDATER_ERROR_CHECK(statvfs64("/sdcard", &updaterVfs) >= 0, "Statvfs read /sdcard error!", return UPDATE_ERROR); - auto freeSpaceSize = static_cast(updaterVfs.f_bfree); - auto blockSize = static_cast(updaterVfs.f_bsize); - uint64_t totalFreeSize = freeSpaceSize * blockSize; - UPDATER_ERROR_CHECK(totalFreeSize > static_cast(info->unpackedSize), - "Can not update, free space is not enough", - ShowText(g_updateInfoLabel, "Free space is not enough"); return UPDATE_ERROR); - } else { - UPDATER_ERROR_CHECK(statvfs64("/data", &updaterVfs) >= 0, "Statvfs read /data error!", return UPDATE_ERROR); - UPDATER_ERROR_CHECK(updaterVfs.f_bfree * updaterVfs.f_bsize > (info->unpackedSize + MAX_LOG_SPACE), - "Can not update, free space is not enough", - ShowText(g_updateInfoLabel, "Free space is not enough"); return UPDATE_ERROR); - } - return UPDATE_SUCCESS; -} - -static inline void ProgressSmoothHandler() +static void ProgressSmoothHandler() { while (g_tmpProgressValue < FULL_PERCENT_PROGRESS) { int gap = FULL_PERCENT_PROGRESS - g_tmpProgressValue; @@ -161,7 +122,9 @@ static inline void ProgressSmoothHandler() if (g_tmpProgressValue >= FULL_PERCENT_PROGRESS || increase == 0) { break; } else { - g_progressBar->SetProgressValue(g_tmpProgressValue); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(g_tmpProgressValue); + } std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); } } @@ -170,25 +133,27 @@ static inline void ProgressSmoothHandler() UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, const std::string &packagePath, int retryCount) { - g_progressBar->Hide(); + if (GetProgressBar() != nullptr) { + GetProgressBar()->Hide(); + } ShowUpdateFrame(true); UPDATER_ERROR_CHECK(pkgManager != nullptr, "Fail to GetPackageInstance", return UPDATE_CORRUPT); - UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(g_updateInfoLabel, "update failed"); - return UPDATE_ERROR); + TextLabel *updateInfoLabel = GetUpdateInfoLabel(); + UPDATER_ERROR_CHECK(updateInfoLabel != nullptr, "Fail to updateInfoLabel", return UPDATE_CORRUPT); LOG(INFO) << "Verify package..."; - g_updateInfoLabel->SetText("Verify package..."); + updateInfoLabel->SetText("Verify package..."); UPDATER_ERROR_CHECK(access(packagePath.c_str(), 0) == 0, "package is not exist", - ShowText(g_updateInfoLabel, "package is not exist"); return UPDATE_CORRUPT); + ShowText(GetUpdateInfoLabel(), "package is not exist"); return UPDATE_CORRUPT); if (retryCount > 0) { LOG(INFO) << "Retry for " << retryCount << " time(s)"; } else { - UpdaterStatus ret = IsSpaceCapacitySufficient(packagePath); + UpdaterStatus ret = static_cast(IsSpaceCapacitySufficient(packagePath)); // 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_ERROR) { + if (ret == UPDATE_SPACE_NOTENOUGH || ret == UPDATE_ERROR) { return ret; } else if (ret == UPDATE_SUCCESS) { pkgManager = PkgManager::GetPackageInstance(); @@ -197,7 +162,7 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons int32_t verifyret = GetUpdatePackageInfo(pkgManager, packagePath); UPDATER_ERROR_CHECK(verifyret == PKG_SUCCESS, "Verify package Fail...", - ShowText(g_updateInfoLabel, "Verify package Fail..."); return UPDATE_CORRUPT); + ShowText(GetUpdateInfoLabel(), "Verify package Fail..."); return UPDATE_CORRUPT); LOG(INFO) << "Package verified. start to install package..."; int32_t versionRet = UpdatePreProcess(pkgManager, packagePath); UPDATER_ERROR_CHECK(versionRet == PKG_SUCCESS, "Version Check Fail...", return UPDATE_CORRUPT); @@ -206,21 +171,49 @@ UpdaterStatus DoInstallUpdaterPackage(PkgManager::PkgManagerPtr pkgManager, cons UpdaterStatus updateRet = StartUpdaterProc(pkgManager, packagePath, retryCount, maxTemperature); if (updateRet == UPDATE_SUCCESS) { ProgressSmoothHandler(); - g_progressBar->SetProgressValue(FULL_PERCENT_PROGRESS); - g_updateInfoLabel->SetText("Update success, reboot now"); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(FULL_PERCENT_PROGRESS); + } + updateInfoLabel->SetText("Update success, reboot now"); std::this_thread::sleep_for(std::chrono::milliseconds(SHOW_FULL_PROGRESS_TIME)); LOG(INFO)<< "update success , do reboot now"; } else { - g_updateInfoLabel->SetText("Install failed."); + updateInfoLabel->SetText("Install failed."); LOG(ERROR) << "Install package failed."; } return updateRet; } +static void HandleProgressSet(const std::vector &output) +{ + UPDATER_ERROR_CHECK(output.size() >= DEFAULT_PROCESS_NUM, "check output fail", return); + auto outputInfo = Trim(output[1]); + float frac = 0.0; + frac = std::stof(output[1]); + if (frac >= -EPSINON && frac <= EPSINON) { + return; + } else { + g_tmpProgressValue = static_cast(frac * g_percentage); + } + if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) { + g_tmpValue += g_percentage; + return; + } + g_tmpProgressValue = g_tmpProgressValue + g_tmpValue; + if (g_tmpProgressValue == 0) { + return; + } + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(g_tmpProgressValue); + } +} static void HandleChildOutput(const std::string &buffer, int32_t bufferLen, bool &retryUpdate) { UPDATER_CHECK_ONLY_RETURN(bufferLen != 0, return); + TextLabel *updateInfoLabel = GetUpdateInfoLabel(); + UPDATER_ERROR_CHECK(updateInfoLabel != nullptr, "Fail to updateInfoLabel", return); + std::string str = buffer; std::vector output = SplitString(str, ":"); UPDATER_ERROR_CHECK(output.size() >= 1, "check output fail", return); @@ -242,32 +235,17 @@ static void HandleChildOutput(const std::string &buffer, int32_t bufferLen, if (progress.size() != DEFAULT_PROCESS_NUM) { LOG(ERROR) << "show progress with wrong arguments"; } else { - g_progressBar->Show(); - g_updateInfoLabel->SetText("Start to install package."); + if (GetProgressBar() != nullptr) { + GetProgressBar()->Show(); + } + updateInfoLabel->SetText("Start to install package."); frac = std::stof(progress[0]); g_percentage = static_cast(frac * FULL_PERCENT_PROGRESS); } } else if (outputHeader == "set_progress") { - UPDATER_ERROR_CHECK(output.size() >= DEFAULT_PROCESS_NUM, "check output fail", return); - auto outputInfo = Trim(output[1]); - float frac = 0.0; - frac = std::stof(output[1]); - if (frac >= -EPSINON && frac <= EPSINON) { - return; - } else { - g_tmpProgressValue = static_cast(frac * g_percentage); - } - if (frac >= FULL_EPSINON && g_tmpValue + g_percentage < FULL_PERCENT_PROGRESS) { - g_tmpValue += g_percentage; - return; - } - g_tmpProgressValue = g_tmpProgressValue + g_tmpValue; - if (g_tmpProgressValue == 0) { - return; - } - g_progressBar->SetProgressValue(g_tmpProgressValue); + HandleProgressSet(output); } else { - LOG(WARNING) << "Child process returns unexpected message."; + LOG(DEBUG) << "Child process returns unexpected message: " << outputHeader; } } @@ -279,12 +257,11 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, const std:: UPDATER_ERROR_CHECK(pkgManager != nullptr, "Fail to GetPackageInstance", return UPDATE_CORRUPT); int pipeRead = pfd[0]; int pipeWrite = pfd[1]; - UPDATER_ERROR_CHECK(ExtractUpdaterBinary(pkgManager, UPDATER_BINARY) == 0, "Updater: cannot extract updater binary from update package.", return UPDATE_CORRUPT); g_tmpProgressValue = 0; - if (g_progressBar != nullptr) { - g_progressBar->SetProgressValue(0); + if (GetProgressBar() != nullptr) { + GetProgressBar()->SetProgressValue(0); } pid_t pid = fork(); UPDATER_CHECK_ONLY_RETURN(pid >= 0, ERROR_CODE(CODE_FORK_FAIL); return UPDATE_ERROR); @@ -325,13 +302,13 @@ UpdaterStatus StartUpdaterProc(PkgManager::PkgManagerPtr pkgManager, const std:: } close(pipeWrite); // close write endpoint - char buffer[MAX_BUFFER_SIZE]; + char buffer[MAX_BUFFER_SIZE] = {0}; bool retryUpdate = false; FILE* fromChild = fdopen(pipeRead, "r"); UPDATER_ERROR_CHECK(fromChild != nullptr, "fdopen pipeRead failed", return UPDATE_ERROR); while (fgets(buffer, MAX_BUFFER_SIZE - 1, fromChild) != nullptr) { size_t n = strlen(buffer); - if (buffer[n - 1] == '\n') { + if (n > 0 && buffer[n - 1] == '\n') { buffer[n - 1] = '\0'; } HandleChildOutput(buffer, MAX_BUFFER_SIZE, retryUpdate); diff --git a/services/updater_binary/BUILD.gn b/services/updater_binary/BUILD.gn index 7e8046c9e655db82578527bd51270f6d0337c1aa..a6acef5840a2eb7c4654b3b7db47fa19c229bcb2 100644 --- a/services/updater_binary/BUILD.gn +++ b/services/updater_binary/BUILD.gn @@ -53,11 +53,13 @@ ohos_executable("updater_binary") { "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] + external_deps = [ "init:libbegetutil" ] + install_enable = true part_name = "updater" } diff --git a/services/updater_binary/main.cpp b/services/updater_binary/main.cpp index 6f145ce3ff31d9003935bdddadff88d8c8e34136..68aaaff57286f0bd9c7d3deddb8eb4364aaa255c 100644 --- a/services/updater_binary/main.cpp +++ b/services/updater_binary/main.cpp @@ -24,6 +24,7 @@ #include "utils.h" using namespace updater; +#ifndef UPDATER_UT int main(int argc, char **argv) { InitUpdaterLogger("UPDATER_BINARY", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); @@ -31,7 +32,6 @@ int main(int argc, char **argv) LOG(ERROR) << "Invalid arguments."; return EXIT_INVALID_ARGS; } - 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) { @@ -42,3 +42,4 @@ int main(int argc, char **argv) std::string packagePath = argv[0]; return ProcessUpdater(retry, pipeFd, packagePath, utils::GetCertName()); } +#endif diff --git a/services/updater_binary/update_image_block.cpp b/services/updater_binary/update_image_block.cpp index 4e049fd2bcdbed2766eb6484affa5dc8cc4b356b..32ff33b9fb8f82320fe0b823c565677d1ba8bbfd 100644 --- a/services/updater_binary/update_image_block.cpp +++ b/services/updater_binary/update_image_block.cpp @@ -167,13 +167,14 @@ static int32_t GetUpdateBlockInfo(struct UpdateBlockInfo &infos, uscript::UScrip } static int32_t ExecuteTransferCommand(int fd, const std::vector &lines, uscript::UScriptEnv &env, - uscript::UScriptContext &context) + uscript::UScriptContext &context, const std::string &partitionName) { TransferManagerPtr tm = TransferManager::GetTransferManagerInstance(); auto globalParams = tm->GetGlobalParams(); auto writerThreadInfo = globalParams->writerThreadInfo.get(); globalParams->storeBase = "/data/updater/update_tmp"; + globalParams->retryFile = std::string("/data/updater") + partitionName + "_retry"; LOG(INFO) << "Store base path is " << globalParams->storeBase; int32_t ret = Store::CreateNewSpace(globalParams->storeBase, !globalParams->env->IsRetry()); UPDATER_ERROR_CHECK(ret != -1, "Error to create new store space", @@ -247,7 +248,7 @@ static int32_t DoExecuteUpdateBlock(UpdateBlockInfo &infos, uscript::UScriptEnv int fd = open(infos.devPath.c_str(), O_RDWR | O_LARGEFILE); UPDATER_ERROR_CHECK (fd != -1, "Failed to open block", env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE); - int32_t ret = ExecuteTransferCommand(fd, lines, env, context); + int32_t ret = ExecuteTransferCommand(fd, lines, env, context, infos.partitionName); fsync(fd); close(fd); fd = -1; @@ -344,11 +345,11 @@ int32_t UScriptInstructionBlockCheck::Execute(uscript::UScriptEnv &env, uscript: LOG(INFO) << "BlockSet::ReadDataFromBlock lseek64"; ret = lseek64(fd, static_cast(it->first * H_BLOCK_SIZE), SEEK_SET); UPDATER_ERROR_CHECK(ret != -1, "Failed to seek", - return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); + close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); size_t size = (it->second - it->first) * H_BLOCK_SIZE; LOG(INFO) << "BlockSet::ReadDataFromBlock Read " << size << " from block"; UPDATER_ERROR_CHECK(utils::ReadFully(fd, block_buff.data() + pos, size), "Failed to read", - return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); + close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); pos += size; } @@ -364,6 +365,7 @@ int32_t UScriptInstructionBlockCheck::Execute(uscript::UScriptEnv &env, uscript: } LOG(INFO) << "UScriptInstructionBlockCheck::Execute Success"; context.PushParam(USCRIPT_SUCCESS); + close(fd); return USCRIPT_SUCCESS; } @@ -404,11 +406,11 @@ int32_t UScriptInstructionShaCheck::Execute(uscript::UScriptEnv &env, uscript::U for (; it != blk.End(); ++it) { ret = lseek64(fd, static_cast(it->first * H_BLOCK_SIZE), SEEK_SET); UPDATER_ERROR_CHECK(ret != -1, "Failed to seek", - return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); + close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); for (size_t i = it->first; i < it->second; ++i) { UPDATER_ERROR_CHECK(utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE), "Failed to read", - return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); + close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE); } } @@ -416,9 +418,10 @@ int32_t UScriptInstructionShaCheck::Execute(uscript::UScriptEnv &env, uscript::U SHA256_Final(digest, &ctx); std::string resultSha = utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH); UPDATER_ERROR_CHECK(resultSha == contrastSha, "Different sha256, cannot continue", - return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); + close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context)); LOG(INFO) << "UScriptInstructionShaCheck::Execute Success"; context.PushParam(USCRIPT_SUCCESS); + close(fd); return USCRIPT_SUCCESS; } } diff --git a/services/updater_binary/update_partitions.cpp b/services/updater_binary/update_partitions.cpp index 81f26e8b45bba781e3f13d7c648e16d5ed528050..89c13a3165560a7d10ee657bb8d88c5b8f3a3e4b 100644 --- a/services/updater_binary/update_partitions.cpp +++ b/services/updater_binary/update_partitions.cpp @@ -48,24 +48,25 @@ int UpdatePartitions::ParsePartitionInfo(const std::string &partitionInfo, Parti return 0; } cJSON* thisPartition = cJSON_GetArrayItem(partitions, i); - UPDATER_ERROR_CHECK(thisPartition != nullptr, "Error get thisPartion", free(myPartition); break); + UPDATER_ERROR_CHECK(thisPartition != nullptr, "Error get thisPartion", free(myPartition); + myPartition = nullptr; break); cJSON* item = cJSON_GetObjectItem(thisPartition, "start"); - UPDATER_ERROR_CHECK(item != nullptr, "Error get start", free(myPartition); break); + UPDATER_ERROR_CHECK(item != nullptr, "Error get start", free(myPartition); myPartition = nullptr; break); myPartition->start = item->valueint; item = cJSON_GetObjectItem(thisPartition, "length"); - UPDATER_ERROR_CHECK(item != nullptr, "Error get length", free(myPartition); break); + UPDATER_ERROR_CHECK(item != nullptr, "Error get length", free(myPartition); myPartition = nullptr; break); myPartition->length = item->valueint; myPartition->partNum = 0; myPartition->devName = "mmcblk0px"; item = cJSON_GetObjectItem(thisPartition, "partName"); - UPDATER_ERROR_CHECK(item != nullptr, "Error get partName", free(myPartition); break); + UPDATER_ERROR_CHECK(item != nullptr, "Error get partName", free(myPartition); myPartition = nullptr; break); myPartition->partName = (item->valuestring); item = cJSON_GetObjectItem(thisPartition, "fsType"); - UPDATER_ERROR_CHECK(item != nullptr, "Error get fsType", free(myPartition); break); + UPDATER_ERROR_CHECK(item != nullptr, "Error get fsType", free(myPartition); myPartition = nullptr; break); myPartition->fsType = (item->valuestring); LOG(INFO) << " "; @@ -84,7 +85,7 @@ int UpdatePartitions::DoNewPartitions(PartitonList &newPartList) if (ret <= 0) { LOG(INFO) << "do_partitions FAIL "; } else if (ret == 1) { - LOG(INFO) << "partitions not changed,Skip. "; + LOG(INFO) << "partitions not changed, Skip"; } else if (ret > 1) { LOG(INFO) << "do_partitions success reboot"; #ifndef UPDATER_UT @@ -116,7 +117,8 @@ int32_t UpdatePartitions::Execute(uscript::UScriptEnv &env, uscript::UScriptCont std::string tmpPath1 = tmpPath + filePath; ret = env.GetPkgManager()->CreatePkgStream(outStream, tmpPath1, info->unpackedSize, PkgStream::PkgStreamType_Write); - UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", return USCRIPT_ERROR_EXECUTE); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", + return USCRIPT_ERROR_EXECUTE); ret = env.GetPkgManager()->ExtractFile(filePath, outStream); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE); diff --git a/services/updater_binary/update_processor.cpp b/services/updater_binary/update_processor.cpp index 234b59364de4b710c83df5be8b6bdc80d5f96926..8bcc08c0af0badf4efa0a63807de54f4f9041ebd 100644 --- a/services/updater_binary/update_processor.cpp +++ b/services/updater_binary/update_processor.cpp @@ -43,8 +43,8 @@ UpdaterEnv::~UpdaterEnv() void UpdaterEnv::PostMessage(const std::string &cmd, std::string content) { - if (pipeWrite_ != nullptr) { - fprintf(pipeWrite_, "%s:%s\n", cmd.c_str(), content.c_str()); + if (postMessage_ != nullptr) { + postMessage_(cmd.c_str(), content.c_str()); } } @@ -108,6 +108,7 @@ int UScriptInstructionRawImageWrite::RawImageWriteProcessor(const PkgBuffer &buf if (totalSize_ != 0) { readSize_ += size; writer->GetUpdaterEnv()->PostMessage("set_progress", std::to_string((float)readSize_ / totalSize_)); + writer->GetUpdaterEnv()->PostMessage("data", std::to_string(size)); } return PKG_SUCCESS; @@ -117,7 +118,10 @@ int32_t UScriptInstructionRawImageWrite::Execute(uscript::UScriptEnv &env, uscri { std::string partitionName; int32_t ret = context.GetParam(0, partitionName); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get param", return ret); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get partitionName", return ret); + std::string imageFilename; + ret = context.GetParam(1, imageFilename); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to get imageFilename", return ret); if (env.IsRetry()) { LOG(DEBUG) << "Retry updater, check if current partition updated already during last time"; @@ -136,16 +140,16 @@ int32_t UScriptInstructionRawImageWrite::Execute(uscript::UScriptEnv &env, uscri // Extract partition information hpackage::PkgManager::StreamPtr outStream = nullptr; - const FileInfo *info = env.GetPkgManager()->GetFileInfo(partitionName); + const FileInfo *info = env.GetPkgManager()->GetFileInfo(imageFilename); UPDATER_ERROR_CHECK(info != nullptr, "Error to get file info", DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); totalSize_ = info->unpackedSize; ret = env.GetPkgManager()->CreatePkgStream(outStream, - partitionName, RawImageWriteProcessor, writer.get()); - UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", + imageFilename, RawImageWriteProcessor, writer.get()); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); - ret = env.GetPkgManager()->ExtractFile(partitionName, outStream); + ret = env.GetPkgManager()->ExtractFile(imageFilename, outStream); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", env.GetPkgManager()->ClosePkgStream(outStream); DataWriter::ReleaseDataWriter(writer); return USCRIPT_ERROR_EXECUTE); @@ -183,7 +187,8 @@ int32_t UScriptInstructionSparseImageWrite::Execute(uscript::UScriptEnv &env, us ret = env.GetPkgManager()->CreatePkgStream(outStream, partitionName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap); - UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", return USCRIPT_ERROR_EXECUTE); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS && outStream != nullptr, "Error to create output stream", + return USCRIPT_ERROR_EXECUTE); ret = env.GetPkgManager()->ExtractFile(partitionName, outStream); UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file", @@ -209,6 +214,25 @@ int32_t UScriptInstructionSparseImageWrite::Execute(uscript::UScriptEnv &env, us DataWriter::ReleaseDataWriter(writer); return ret; } + +int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, PostMessageFunction postMessage) +{ + UpdaterEnv* env = new UpdaterEnv(pkgManager, postMessage, retry); + UPDATER_ERROR_CHECK(env != nullptr, "Fail to create env", return EXIT_PARSE_SCRIPT_ERROR); + int ret = 0; + ScriptManager* scriptManager = ScriptManager::GetScriptManager(env); + UPDATER_ERROR_CHECK(scriptManager != nullptr, "Fail to create scriptManager", + ScriptManager::ReleaseScriptManager(); + delete env; + return EXIT_PARSE_SCRIPT_ERROR); + for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) { + ret = scriptManager->ExecuteScript(i); + UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Fail to execute script", break); + } + ScriptManager::ReleaseScriptManager(); + delete env; + return ret; +} } // updater int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath) @@ -224,35 +248,15 @@ int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::vector components; int32_t ret = pkgManager->LoadPackage(packagePath, keyPath, components); UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "Fail to load package", - fclose(pipeWrite); - pipeWrite = nullptr; PkgManager::ReleasePackageInstance(pkgManager); return EXIT_INVALID_ARGS); - UpdaterEnv* env = new UpdaterEnv(pkgManager, pipeWrite, retry); - UPDATER_ERROR_CHECK(env != nullptr, "Fail to create env", - fclose(pipeWrite); - pipeWrite = nullptr; - PkgManager::ReleasePackageInstance(pkgManager); - env = nullptr; - return EXIT_PARSE_SCRIPT_ERROR); - ScriptManager* scriptManager = ScriptManager::GetScriptManager(env); - UPDATER_ERROR_CHECK(scriptManager != nullptr, "Fail to create scriptManager", - fclose(pipeWrite); - pipeWrite = nullptr; - delete env; - env = nullptr; - PkgManager::ReleasePackageInstance(pkgManager); - ScriptManager::ReleaseScriptManager(); - return EXIT_PARSE_SCRIPT_ERROR); - for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) { - ret = scriptManager->ExecuteScript(i); - UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Fail to execute script", break); - } - - delete env; - env = nullptr; - ScriptManager::ReleaseScriptManager(); + ret = updater::ExecUpdate(pkgManager, retry, + [&pipeWrite](const char *cmd, const char *content) { + if (pipeWrite != nullptr) { + fprintf(pipeWrite, "%s:%s\n", cmd, content); + } + }); PkgManager::ReleasePackageInstance(pkgManager); #ifndef UPDATER_UT fclose(pipeWrite); diff --git a/services/updater_main.cpp b/services/updater_main.cpp index 56d98839b28db2385eef73fd5b250b04acffc936..9b393a6d3f2354c575c7d419565461fb553ad043 100644 --- a/services/updater_main.cpp +++ b/services/updater_main.cpp @@ -49,8 +49,8 @@ using namespace updater::utils; extern TextLabel *g_logLabel; extern TextLabel *g_logResultLabel; -extern TextLabel *g_updateInfoLabel; -extern int g_updateFlag; + +constexpr int DISPLAY_TIME = 1000 * 1000; constexpr struct option OPTIONS[] = { { "update_package", required_argument, nullptr, 0 }, { "retry_count", required_argument, nullptr, 0 }, @@ -106,8 +106,16 @@ UpdaterStatus UpdaterFromSdcard() { #ifndef UPDATER_UT // sdcard fsType only support ext4/vfat + std::string sdcardStr = GetBlockDeviceByMountPoint(SDCARD_PATH); + if (!IsSDCardExist(sdcardStr)) { + if (errno == ENOENT) { + ShowText(g_logLabel, "Cannot detect SdCard!"); + } else { + ShowText(g_logLabel, "Detecting SdCard abnormally!"); + } + return UPDATE_ERROR; + } if (MountForPath(SDCARD_PATH) != 0) { - std::string sdcardStr = GetBlockDeviceByMountPoint(SDCARD_PATH); int ret = mount(sdcardStr.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL); UPDATER_WARING_CHECK(ret == 0, "MountForPath /sdcard failed!", return UPDATE_ERROR); } @@ -121,6 +129,8 @@ UpdaterStatus UpdaterFromSdcard() STAGE(UPDATE_STAGE_BEGIN) << "UpdaterFromSdcard"; LOG(INFO) << "UpdaterFromSdcard start, sdcard updaterPath : " << SDCARD_CARD_PKG_PATH; + g_logLabel->SetText("Don't remove SD Card!"); + usleep(DISPLAY_TIME); UpdaterStatus updateRet = DoInstallUpdaterPackage(pkgManager, SDCARD_CARD_PKG_PATH.c_str(), 0); if (updateRet != UPDATE_SUCCESS) { std::this_thread::sleep_for(std::chrono::milliseconds(UI_SHOW_DURATION)); @@ -155,11 +165,13 @@ static UpdaterStatus InstallUpdaterPackage(UpdaterParams &upParams, const std::v "ClearRecordPartitionOffset failed", return UPDATE_ERROR); SetRetryCountToMisc(upParams.retryCount + 1, args); } - + UPDATER_CHECK_ONLY_RETURN(SetupPartitions() == 0, ShowText(GetUpdateInfoLabel(), "Setup partitions failed"); + return UPDATE_ERROR); 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; @@ -186,7 +198,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, } else if (upParams.factoryWipeData) { LOG(INFO) << "Factory level FactoryReset begin"; status = UPDATE_SUCCESS; - g_updateFlag = 1; + SetUpdateFlag(1); ShowUpdateFrame(true); DoProgress(); UPDATER_ERROR_CHECK(FactoryReset(FACTORY_WIPE_DATA, "/data") == 0, "FactoryReset factory level failed", @@ -201,7 +213,7 @@ static UpdaterStatus StartUpdaterEntry(PkgManager::PkgManagerPtr manager, } else if (upParams.userWipeData) { LOG(INFO) << "User level FactoryReset begin"; status = UPDATE_SUCCESS; - g_updateFlag = 1; + SetUpdateFlag(1); ShowUpdateFrame(true); DoProgress(); UPDATER_ERROR_CHECK(FactoryReset(USER_WIPE_DATA, "/data") == 0, "FactoryReset user level failed", @@ -211,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)); } } @@ -264,106 +276,10 @@ static UpdaterStatus StartUpdater(PkgManager::PkgManagerPtr manager, const std:: return StartUpdaterEntry(manager, args, upParams); } -static bool DeleteUpdaterPath(const std::string &path) -{ - auto pDir = std::unique_ptr(opendir(path.c_str()), closedir); - UPDATER_INFO_CHECK_NOT_RETURN(pDir != nullptr, "Can not open dir"); - - struct dirent *dp = nullptr; - if (pDir != nullptr) { - while ((dp = readdir(pDir.get())) != nullptr) { - std::string currentName(dp->d_name); - if (currentName[0] != '.' && (currentName.compare("log") != 0)) { - std::string tmpName(path); - tmpName.append("/" + currentName); - if (tmpName.find(".") == std::string::npos) { - DeleteUpdaterPath(tmpName); - } -#ifndef UPDATER_UT - remove(tmpName.c_str()); -#endif - } - } - } - return true; -} - -static bool ClearMisc() -{ - struct UpdateMessage cleanBoot {}; - UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true, - "ClearMisc clear boot message to misc failed", return false); - auto fp = std::unique_ptr(fopen(MISC_FILE.c_str(), "rb+"), fclose); - UPDATER_FILE_CHECK(fp != nullptr, "WriteVersionCode fopen failed", return false); - fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET); - off_t clearOffset = 0; - UPDATER_FILE_CHECK(fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) == 1, - "ClearMisc write misc initOffset 0 failed", return false); - - struct PartitionRecordInfo cleanPartition {}; - for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset += - sizeof(PartitionRecordInfo)) { - fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET); - UPDATER_FILE_CHECK(fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) == 1, - "ClearMisc write misc cleanPartition failed", return false); - } - return true; -} - -void PostUpdater() -{ - STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; - // clear update misc partition. - 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"); - } - - // delete updater tmp files - if (access(UPDATER_PATH.c_str(), 0) == 0 && access(SDCARD_CARD_PATH.c_str(), 0) != 0) { - UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed"); - } - if (!access(SDCARD_CARD_PATH.c_str(), 0)) { - UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed"); - } - // save logs - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_LOG, UPDATER_LOG) == true, "Copy updater log failed!"); - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_ERROR_CODE_PATH, ERROR_CODE_PATH) == true, - "Copy error code log failed!"); - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; - chmod(UPDATER_LOG.c_str(), mode); - chmod(UPDATER_STAGE_LOG.c_str(), mode); - chmod(ERROR_CODE_PATH.c_str(), mode); - STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; - UPDATER_ERROR_CHECK_NOT_RETURN(CopyUpdaterLogs(TMP_STAGE_LOG, UPDATER_STAGE_LOG) == true, "Copy stage log failed!"); -} - -std::vector ParseParams(int argc, char **argv) -{ - struct UpdateMessage boot {}; - // read from misc - UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(MISC_FILE, boot) == true, - "ReadUpdaterMessage MISC_FILE failed!"); - // 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)) { - UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(COMMAND_FILE, boot) == true, - "ReadUpdaterMessage COMMAND_FILE failed!"); - } - STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; - std::vector parseParams(argv, argv + argc); - boot.update[sizeof(boot.update) - 1] = '\0'; - parseParams = utils::SplitString(boot.update, "\n"); - return parseParams; -} - int UpdaterMain(int argc, char **argv) { UpdaterStatus status = UPDATE_UNKNOWN; PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance(); - InitUpdaterLogger("UPDATER", TMP_LOG, TMP_STAGE_LOG, TMP_ERROR_CODE_PATH); - SetLogLevel(INFO); - LoadFstab(); std::vector args = ParseParams(argc, argv); LOG(INFO) << "Ready to start"; @@ -382,7 +298,7 @@ int UpdaterMain(int argc, char **argv) return 0; } #endif - PostUpdater(); + PostUpdater(true); utils::DoReboot(""); return 0; } diff --git a/services/updater_main.h b/services/updater_main.h index c2862850c4b4121927ffce217070dd3eb3524875..fef8b7a8b443e726941a18bff640c4d59e83bc6b 100644 --- a/services/updater_main.h +++ b/services/updater_main.h @@ -35,10 +35,6 @@ struct UpdaterParams { int UpdaterMain(int argc, char **argv); -std::vector ParseParams(int argc, char **argv); - -void PostUpdater(); - int FactoryReset(FactoryResetMode mode, const std::string &path); UpdaterStatus UpdaterFromSdcard(); diff --git a/services/updater_utils.cpp b/services/updater_utils.cpp new file mode 100755 index 0000000000000000000000000000000000000000..dc928c749c9385ec5f244a57ee364f11bad13224 --- /dev/null +++ b/services/updater_utils.cpp @@ -0,0 +1,320 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "applypatch/partition_record.h" +#include "flashd/flashd.h" +#include "log/log.h" +#include "misc_info/misc_info.h" +#include "package/pkg_manager.h" +#include "securec.h" +#include "updater/updater.h" +#include "updater/updater_const.h" +#include "updater_ui.h" +#include "utils.h" + +namespace { +static constexpr int USER_ROOT_AUTHORITY = 0; +static constexpr int GROUP_SYS_AUTHORITY = 1000; +} +namespace updater { +using namespace hpackage; +using namespace updater::utils; +void CompressLogs(const std::string &name) +{ + PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); + UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return); + std::vector> files; + // Build the zip file to be packaged + std::vector testFileNames; + std::string realName = name.substr(name.find_last_of("/") + 1); + testFileNames.push_back(realName); + for (auto name : testFileNames) { + ZipFileInfo file; + file.fileInfo.identity = name; + file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; + file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; + std::string fileName = "/data/updater/log/" + name; + files.push_back(std::pair(fileName, file)); + } + + PkgInfo pkgInfo; + pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; + pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; + pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; + + char realTime[MAX_TIME_SIZE] = { 0 }; + auto sysTime = std::chrono::system_clock::now(); + auto currentTime = std::chrono::system_clock::to_time_t(sysTime); + struct tm *localTime = std::localtime(¤tTime); + if (localTime != nullptr) { + std::strftime(realTime, sizeof(realTime), "%H_%M_%S", localTime); + } + char pkgName[MAX_LOG_NAME_SIZE]; + UPDATER_CHECK_ONLY_RETURN(snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1, + "/data/updater/log/%s_%s.zip", realName.c_str(), realTime) != -1, return); + int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files); + UPDATER_CHECK_ONLY_RETURN(ret != 0, return); + UPDATER_CHECK_ONLY_RETURN(DeleteFile(name) == 0, return); +} + +bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog) +{ + UPDATER_WARING_CHECK(MountForPath(UPDATER_LOG_DIR) == 0, "MountForPath /data/log failed!", return false); + if (access(UPDATER_LOG_DIR.c_str(), 0) != 0) { + UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_LOG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), + "MkdirRecursive error!", return false); + UPDATER_ERROR_CHECK(chown(UPDATER_PATH.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY) == 0, + "Chown failed!", return false); + UPDATER_ERROR_CHECK(chmod(UPDATER_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0, + "Chmod failed!", return false); + } + + FILE *dFp = fopen(dLog.c_str(), "ab+"); + UPDATER_ERROR_CHECK(dFp != nullptr, "open log failed", return false); + + FILE *sFp = fopen(sLog.c_str(), "r"); + UPDATER_ERROR_CHECK(sFp != nullptr, "open log failed", fclose(dFp); + return false); + + char buf[MAX_LOG_BUF_SIZE]; + size_t bytes; + while ((bytes = fread(buf, 1, sizeof(buf), sFp)) != 0) { + int ret = fwrite(buf, 1, bytes, dFp); + if (ret < 0) { + break; + } + } + (void)fseek(dFp, 0, SEEK_END); + UPDATER_INFO_CHECK(ftell(dFp) < MAX_LOG_SIZE, "log size greater than 5M!", CompressLogs(dLog)); + sync(); + (void)fclose(sFp); + (void)fclose(dFp); + return true; +} + +static bool IsDir(const std::string &path) +{ + struct stat st {}; + if (stat(path.c_str(), &st) < 0) { + return false; + } + return S_ISDIR(st.st_mode); +} + +static bool DeleteUpdaterPath(const std::string &path) +{ + auto pDir = std::unique_ptr(opendir(path.c_str()), closedir); + UPDATER_INFO_CHECK_NOT_RETURN(pDir != nullptr, "Can not open dir"); + if (pDir == nullptr) { + return true; + } + struct dirent *dp = nullptr; + while ((dp = readdir(pDir.get())) != nullptr) { + std::string currentName(dp->d_name); + if (currentName[0] != '.' && (currentName.compare("log") != 0)) { + std::string tmpName(path); + tmpName.append("/" + currentName); + if (IsDir(tmpName)) { + DeleteUpdaterPath(tmpName); + } +#ifndef UPDATER_UT + remove(tmpName.c_str()); +#endif + } + } + return true; +} + +static bool ClearMisc() +{ + struct UpdateMessage cleanBoot {}; + UPDATER_ERROR_CHECK(WriteUpdaterMessage(MISC_FILE, cleanBoot) == true, + "ClearMisc clear boot message to misc failed", return false); + auto fp = std::unique_ptr(fopen(MISC_FILE.c_str(), "rb+"), fclose); + UPDATER_FILE_CHECK(fp != nullptr, "WriteVersionCode fopen failed", return false); + (void)fseek(fp.get(), PARTITION_RECORD_OFFSET, SEEK_SET); + off_t clearOffset = 0; + UPDATER_FILE_CHECK(fwrite(&clearOffset, sizeof(off_t), 1, fp.get()) == 1, + "ClearMisc write misc initOffset 0 failed", return false); + + struct PartitionRecordInfo cleanPartition {}; + for (size_t tmpOffset = 0; tmpOffset < PARTITION_UPDATER_RECORD_MSG_SIZE; tmpOffset += + sizeof(PartitionRecordInfo)) { + (void)fseek(fp.get(), PARTITION_RECORD_START + tmpOffset, SEEK_SET); + UPDATER_FILE_CHECK(fwrite(&cleanPartition, sizeof(PartitionRecordInfo), 1, fp.get()) == 1, + "ClearMisc write misc cleanPartition failed", return false); + } + return true; +} + +bool IsSDCardExist(const std::string &sdcardPath) +{ + // Record system error codes. + int save_errno = errno; + struct stat st {}; + if (stat(sdcardPath.c_str(), &st) < 0) { + return false; + } else { + errno = save_errno; + return true; + } +} + +void PostUpdaterForSdcard(std::string &updaterLogPath, std::string &stageLogPath, std::string &errorCodePath) +{ + if (SetupPartitions() != 0) { + ShowText(GetUpdateInfoLabel(), "Mount data failed."); + LOG(ERROR) << "Mount for /data failed."; + std::string sdcardPath = GetBlockDeviceByMountPoint(SDCARD_PATH); + if (IsSDCardExist(sdcardPath)) { + if (MountForPath(SDCARD_PATH) != 0) { + int ret = mount(sdcardPath.c_str(), SDCARD_PATH.c_str(), "vfat", 0, NULL); + UPDATER_WARING_CHECK(ret == 0, "Mount for /sdcard failed!", return); + } + updaterLogPath = "/sdcard/updater/log/updater_log"; + stageLogPath = "/sdcard/updater/log/updater_stage_log"; + errorCodePath = "/sdcard/updater/log/error_code.log"; + } + } + return; +} + +void PostUpdater(bool clearMisc) +{ + STAGE(UPDATE_STAGE_BEGIN) << "PostUpdater"; + std::string updaterLogPath = "/data/updater/log/updater_log"; + std::string stageLogPath = "/data/updater/log/updater_stage_log"; + std::string errorCodePath = "/data/updater/log/error_code.log"; + PostUpdaterForSdcard(updaterLogPath, stageLogPath, errorCodePath); + // clear update misc partition. + 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"); + } + + // delete updater tmp files + if (access(UPDATER_PATH.c_str(), 0) == 0 && access(SDCARD_CARD_PATH.c_str(), 0) != 0) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(UPDATER_PATH), "DeleteUpdaterPath failed"); + } + if (!access(SDCARD_CARD_PATH.c_str(), 0)) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(SDCARD_CARD_PATH), "Delete sdcard path failed"); + } + if (access(flashd::FLASHD_FILE_PATH.c_str(), 0) == 0) { + UPDATER_ERROR_CHECK_NOT_RETURN(DeleteUpdaterPath(flashd::FLASHD_FILE_PATH), "DeleteUpdaterPath failed"); + } + + // save logs + bool ret = CopyUpdaterLogs(TMP_LOG, updaterLogPath); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy updater log failed!"); + ret = CopyUpdaterLogs(TMP_ERROR_CODE_PATH, errorCodePath); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error code log failed!"); + ret = CopyUpdaterLogs(flashd::FLASHD_HDC_LOG_PATH, UPDATER_HDC_LOG); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy error hdc log failed!"); + + mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; + chmod(updaterLogPath.c_str(), mode); + chmod(stageLogPath.c_str(), mode); + chmod(errorCodePath.c_str(), mode); + STAGE(UPDATE_STAGE_SUCCESS) << "PostUpdater"; + ret = CopyUpdaterLogs(TMP_STAGE_LOG, stageLogPath); + UPDATER_ERROR_CHECK_NOT_RETURN(ret, "Copy stage log failed!"); +} + +int IsSpaceCapacitySufficient(const std::string &packagePath) +{ + hpackage::PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance(); + UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return UPDATE_CORRUPT); + std::vector fileIds; + int ret = pkgManager->LoadPackageWithoutUnPack(packagePath, fileIds); + UPDATER_ERROR_CHECK(ret == PKG_SUCCESS, "LoadPackageWithoutUnPack failed", + PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); + const FileInfo *info = pkgManager->GetFileInfo("update.bin"); + UPDATER_ERROR_CHECK(info != nullptr, "update.bin is not exist", + PkgManager::ReleasePackageInstance(pkgManager); return UPDATE_CORRUPT); + uint64_t needSpace = static_cast(info->unpackedSize); + PkgManager::ReleasePackageInstance(pkgManager); + + struct statvfs64 updaterVfs {}; + if (strncmp(packagePath.c_str(), SDCARD_CARD_PATH.c_str(), SDCARD_CARD_PATH.size()) == 0) { // for sdcard + ret = statvfs64(SDCARD_PATH.c_str(), &updaterVfs); + UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /sdcard error!", return UPDATE_ERROR); + } else { + needSpace += MAX_LOG_SPACE; + ret = statvfs64(UPDATER_PATH.c_str(), &updaterVfs); + UPDATER_ERROR_CHECK(ret >= 0, "Statvfs read /data error!", return UPDATE_ERROR); + } + auto freeSpaceSize = static_cast(updaterVfs.f_bfree); + auto blockSize = static_cast(updaterVfs.f_bsize); + uint64_t totalFreeSize = freeSpaceSize * blockSize; + UPDATER_ERROR_CHECK(totalFreeSize > needSpace, + "Can not update, free space is not enough", return UPDATE_SPACE_NOTENOUGH); + return UPDATE_SUCCESS; +} + +std::vector ParseParams(int argc, char **argv) +{ + struct UpdateMessage boot {}; + // read from misc + UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(MISC_FILE, boot) == true, + "ReadUpdaterMessage MISC_FILE failed!"); + // 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)) { + UPDATER_ERROR_CHECK_NOT_RETURN(ReadUpdaterMessage(COMMAND_FILE, boot) == true, + "ReadUpdaterMessage COMMAND_FILE failed!"); + } + STAGE(UPDATE_STAGE_OUT) << "Init Params: " << boot.update; + std::vector parseParams(argv, argv + argc); + boot.update[sizeof(boot.update) - 1] = '\0'; + std::vector parseParams1 = utils::SplitString(boot.update, "\n"); + 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/fuzztest/DoPartitions_fuzzer/BUILD.gn b/test/fuzztest/DoPartitions_fuzzer/BUILD.gn index c48c7433e728822c848195ae3c27eb90e0f42065..7732b73120b3ba1d7723147dee33c1637b8f647b 100644 --- a/test/fuzztest/DoPartitions_fuzzer/BUILD.gn +++ b/test/fuzztest/DoPartitions_fuzzer/BUILD.gn @@ -45,7 +45,7 @@ ohos_fuzztest("DoPartitionsFuzzTest") { "//third_party/bzip2:libbz2", "//third_party/libdrm:libdrm", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", "//utils/native/base:utils", diff --git a/test/fuzztest/DoPartitions_fuzzer/DoPartitions_fuzzer.cpp b/test/fuzztest/DoPartitions_fuzzer/DoPartitions_fuzzer.cpp index 48ea89d754fe9a6c470b3341e2aeddc0c3bddbf0..7a941b3b2ea83aaf628b6d8cd856173668f59baa 100644 --- a/test/fuzztest/DoPartitions_fuzzer/DoPartitions_fuzzer.cpp +++ b/test/fuzztest/DoPartitions_fuzzer/DoPartitions_fuzzer.cpp @@ -26,8 +26,9 @@ #include "securec.h" using namespace updater; +namespace { static constexpr int FSTAB_NAME_LENGTH = 20; - +} static void InitEmmcPartition(struct Partition &part, const std::string &partName, size_t start, size_t length) { part.partName = partName; diff --git a/test/fuzztest/ExtractAndExecuteScript_fuzzer/BUILD.gn b/test/fuzztest/ExtractAndExecuteScript_fuzzer/BUILD.gn index 0632f8e8c246a3d45e3f39fb1d9697e69e2d2762..8f1763b0330eb1fde2757c5b14ca11cbb0f46d62 100644 --- a/test/fuzztest/ExtractAndExecuteScript_fuzzer/BUILD.gn +++ b/test/fuzztest/ExtractAndExecuteScript_fuzzer/BUILD.gn @@ -54,7 +54,7 @@ ohos_fuzztest("ExtractAndExecuteScriptFuzzTest") { "//third_party/bzip2:libbz2", "//third_party/libdrm:libdrm", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", "//utils/native/base:utils", diff --git a/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp b/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp index 99827d8213df45bcb2dc01718c1649916a4de833..748a813139381b51e9148fc919038da97009d4ba 100644 --- a/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp +++ b/test/fuzztest/ReadFstabFromFile_fuzzer/ReadFstabFromFile_fuzzer.cpp @@ -20,7 +20,7 @@ #include #include #include -#include "fstab_api.h" +#include "fs_manager/fs_manager.h" #include "log/log.h" using namespace updater; @@ -29,7 +29,7 @@ namespace OHOS { bool FuzzReadFstabFromFile(const uint8_t* data, size_t size) { FILE *pFile; - Fstab fstab; + Fstab *fstab = NULL; const std::string fstabFile = "ReadFstabFromFile.txt"; pFile = fopen("ReadFstabFromFile.txt", "w+"); @@ -40,9 +40,9 @@ namespace OHOS { fwrite(data, 1, size, pFile); fclose(pFile); - ReadFstabFromFile(fstabFile, fstab); + fstab = ReadFstabFromFile(fstabFile.c_str(), false); remove("ReadFstabFromFile.txt"); - + ReleaseFstab(fstab); return 0; } } diff --git a/test/fuzztest/UpdaterFactoryReset_fuzzer/BUILD.gn b/test/fuzztest/UpdaterFactoryReset_fuzzer/BUILD.gn index b644afb75d9fa5082665397a9ec6ea5e4540c40a..619dabc7247870f9990e105efc0a9cf2a8862cd3 100644 --- a/test/fuzztest/UpdaterFactoryReset_fuzzer/BUILD.gn +++ b/test/fuzztest/UpdaterFactoryReset_fuzzer/BUILD.gn @@ -47,7 +47,7 @@ ohos_fuzztest("UpdaterFactoryResetFuzzTest") { "//third_party/bzip2:libbz2", "//third_party/libdrm:libdrm", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] diff --git a/test/fuzztest/UpdaterFactoryReset_fuzzer/UpdaterFactoryReset_fuzzer.cpp b/test/fuzztest/UpdaterFactoryReset_fuzzer/UpdaterFactoryReset_fuzzer.cpp index db10a9b60419c4dcb02ed1fdfadf2dcbcf307da0..60e10961f99968c478eed2ddd6de5d3c321fe029 100644 --- a/test/fuzztest/UpdaterFactoryReset_fuzzer/UpdaterFactoryReset_fuzzer.cpp +++ b/test/fuzztest/UpdaterFactoryReset_fuzzer/UpdaterFactoryReset_fuzzer.cpp @@ -25,8 +25,9 @@ #include "updater_main.h" using namespace updater; +namespace { static constexpr int FSTAB_NAME_LENGTH = 20; - +} namespace OHOS { bool FuzzFactoryReset(const uint8_t* data, size_t size) { diff --git a/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/BUILD.gn b/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/BUILD.gn index c43acd69e355712ba664123f24815cdc5ac2c0b2..5ef91cb59c550964078846abb8fd2eb2fea4e298 100644 --- a/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/BUILD.gn +++ b/test/fuzztest/UpdaterStartUpdaterProc_fuzzer/BUILD.gn @@ -51,7 +51,7 @@ ohos_fuzztest("UpdaterStartUpdaterProcFuzzTest") { "//third_party/libdrm:libdrm", "//third_party/libpng:libpng", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index d1e9418022c915e7c8e127e0155b22012dfa82ef..6d7a9fc247028f5d920a12a2f6d7542a3782f39b 100755 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -11,7 +11,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//build/ohos.gni") +import("//build/test.gni") + +module_output_path = "updater/updater_test" config("utest_config") { visibility = [ ":*" ] @@ -27,7 +29,9 @@ config("utest_config") { ldflags = [ "--coverage" ] } -ohos_executable("updater_ut") { +ohos_unittest("updater_unittest") { + testonly = true + module_out_path = module_output_path sources = [ "applypatch_test/all_cmd_unittest.cpp", "applypatch_test/applypatch_unittest.cpp", @@ -40,6 +44,8 @@ ohos_executable("updater_ut") { "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", @@ -61,7 +67,6 @@ ohos_executable("updater_ut") { "updater_main_test/updater_main_unittest.cpp", "updater_test/updater_unittest.cpp", "updater_ui_test/updater_ui_unittest.cpp", - "updater_ut_entry.cpp", "updaterkits_test/updaterkits_unittest.cpp", "utils/utils_unittest.cpp", ] @@ -88,9 +93,14 @@ ohos_executable("updater_ut") { "//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/fstab.cpp", "//base/update/updater/services/fs_manager/mount.cpp", "//base/update/updater/services/fs_manager/partitions.cpp", "//base/update/updater/services/log/log.cpp", @@ -129,8 +139,10 @@ ohos_executable("updater_ut") { "//base/update/updater/services/updater_binary/update_partitions.cpp", "//base/update/updater/services/updater_binary/update_processor.cpp", "//base/update/updater/services/updater_main.cpp", + "//base/update/updater/services/updater_utils.cpp", "//base/update/updater/utils/utils.cpp", ] + include_dirs = [ "//base/update/updater/interfaces/kits/include/", "//base/update/updater/interfaces/kits/include/package", @@ -151,6 +163,10 @@ ohos_executable("updater_ut") { "//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", @@ -159,6 +175,9 @@ ohos_executable("updater_ut") { "//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", @@ -169,6 +188,7 @@ ohos_executable("updater_ut") { "//third_party/bzip2", "//third_party/libdrm/include/drm", "//third_party/libdrm", + "//third_party/googletest/googletest/include", "//drivers/framework/ability/sbuf/include", "//drivers/framework/include/platform", "//drivers/framework/include/core", @@ -181,11 +201,11 @@ ohos_executable("updater_ut") { "//third_party/bounds_checking_function/include", ] deps = [ - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", "//base/update/updater/interfaces/kits/misc_info:libmiscinfo", "//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", @@ -194,10 +214,11 @@ ohos_executable("updater_ut") { "//third_party/bounds_checking_function:libsec_static", "//third_party/bzip2:libbz2", "//third_party/cJSON:cjson_static", - "//third_party/googletest:gmock", - "//third_party/googletest:gtest", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/libuv:uv_static", "//third_party/lz4:liblz4_static", - "//third_party/openssl:crypto_source", + "//third_party/openssl:libcrypto_static", "//third_party/openssl:ssl_source", "//third_party/zlib:libz", ] @@ -207,13 +228,21 @@ ohos_executable("updater_ut") { "//base/update/updater/test/unittest:test_update_binary_abnormal", ] + external_deps = [ + "init:libbegetutil", + "startup_l2:syspara", + ] + + cflags_cc = [ "-fexceptions" ] + defines = [ "UPDATER_UT", "BUILD_OHOS", + "HDC_DEBUG", + "HDC_SUPPORT_FLASHD", + "HARMONY_PROJECT", ] - cflags_cc = [ "-fexceptions" ] - public_configs = [ ":utest_config" ] install_enable = true part_name = "updater" diff --git a/test/unittest/applypatch_test/all_cmd_unittest.cpp b/test/unittest/applypatch_test/all_cmd_unittest.cpp index 62768b6824d26ec6ff8e8a31bb81fb331c3af128..489b5b26c8019a88193ccf9815019c8f363c2243 100755 --- a/test/unittest/applypatch_test/all_cmd_unittest.cpp +++ b/test/unittest/applypatch_test/all_cmd_unittest.cpp @@ -24,6 +24,8 @@ #include "log/log.h" #include "utils.h" + +using namespace testing::ext; using namespace updater; using namespace std; namespace updater_ut { @@ -96,7 +98,7 @@ bool AllCmdUnitTest::WriteTestBin(int fd, const uint8_t &data, size_t size) cons // new command is not easy to simulate, it depends on // compression and other condition. // Leave new command to be covered by update_image_block test. -TEST_F(AllCmdUnitTest, allCmd_test_001) +HWTEST_F(AllCmdUnitTest, allCmd_test_001, TestSize.Level1) { TransferManager *tm = TransferManager::GetTransferManagerInstance(); // Read source @@ -162,7 +164,7 @@ int AllCmdUnitTest::AllCmdUnitTestMove(int &fd, std::vector &allCmd return 0; } -TEST_F(AllCmdUnitTest, allCmd_test_002) +HWTEST_F(AllCmdUnitTest, allCmd_test_002, TestSize.Level1) { TransferManagerPtr tm = TransferManager::GetTransferManagerInstance(); std::string filePath = "/tmp/test.bin"; @@ -174,11 +176,11 @@ TEST_F(AllCmdUnitTest, allCmd_test_002) utils::MkdirRecursive(TransferManager::GetTransferManagerInstance()->GetGlobalParams()->storeBase, dirMode); std::vector buffer(bufferSize, 0); int fd = open(filePath.c_str(), O_RDWR | O_CREAT, dirMode); - lseek64(fd, 0, SEEK_SET); - if (fd == -1) { + if (fd < 0) { printf("Failed to open block %s, errno: %d\n", filePath.c_str(), errno); return; } + lseek64(fd, 0, SEEK_SET); auto res = WriteTestBin(fd, *buffer.data(), bufferSize * count); if (!res) { printf("Write to bin error\n"); diff --git a/test/unittest/applypatch_test/applypatch_unittest.cpp b/test/unittest/applypatch_test/applypatch_unittest.cpp index f86307b7bef46b0be2cbff8fe1236350e4406c7e..4f70a0ef14aed9042e3b0dd8c6f398847251e768 100755 --- a/test/unittest/applypatch_test/applypatch_unittest.cpp +++ b/test/unittest/applypatch_test/applypatch_unittest.cpp @@ -63,7 +63,7 @@ void ApplyPatchUnitTest::TearDown() unlink(devPath.c_str()); } -TEST_F(ApplyPatchUnitTest, updater_RawWriter) +HWTEST_F(ApplyPatchUnitTest, updater_RawWriter, TestSize.Level1) { WriteMode mode = WRITE_RAW; uint8_t *addr = nullptr; @@ -92,7 +92,7 @@ TEST_F(ApplyPatchUnitTest, updater_RawWriter) EXPECT_TRUE(ret); int fd = open(devPath.c_str(), O_RDONLY); - EXPECT_GT(fd, 0); + EXPECT_GE(fd, 0); uint8_t buffer[BUFFER_LEN + 1] = {0}; size_t n = read(fd, buffer, BUFFER_LEN); @@ -103,7 +103,7 @@ TEST_F(ApplyPatchUnitTest, updater_RawWriter) DataWriter::ReleaseDataWriter(writer); } -TEST_F(ApplyPatchUnitTest, updater_DataWriterOpenPartition) +HWTEST_F(ApplyPatchUnitTest, updater_DataWriterOpenPartition, TestSize.Level1) { WriteMode mode = WRITE_RAW; std::string partitionName = ""; @@ -116,7 +116,13 @@ TEST_F(ApplyPatchUnitTest, updater_DataWriterOpenPartition) partitionName = "/rawwriter"; auto devPath = GetBlockDeviceByMountPoint(partitionName); - close(open(devPath.c_str(), O_CREAT | O_WRONLY | O_EXCL, 0664)); + int fd = open(devPath.c_str(), O_CREAT | O_WRONLY | O_EXCL, 0664); + if (fd < 0) { + printf("Open %s failed", devPath.c_str()); + FAIL(); + return; + } + close(fd); writer = DataWriter::CreateDataWriter(mode, partitionName); EXPECT_NE(writer, nullptr); ret = writer->OpenPartition(partitionName); @@ -124,7 +130,7 @@ TEST_F(ApplyPatchUnitTest, updater_DataWriterOpenPartition) DataWriter::ReleaseDataWriter(writer); } -TEST_F(ApplyPatchUnitTest, updater_CreateDataWriter) +HWTEST_F(ApplyPatchUnitTest, updater_CreateDataWriter, TestSize.Level1) { std::vector modes = { WRITE_RAW, WRITE_DECRYPT }; std::unique_ptr writer = nullptr; diff --git a/test/unittest/applypatch_test/blockset_unittest.cpp b/test/unittest/applypatch_test/blockset_unittest.cpp index e1b590dbee0ce0c890c541beca60009e09872c3b..866765b274c23b058ed49a6bc849a5eee0cfb73c 100755 --- a/test/unittest/applypatch_test/blockset_unittest.cpp +++ b/test/unittest/applypatch_test/blockset_unittest.cpp @@ -23,6 +23,7 @@ #include "applypatch/command.h" #include "log/log.h" +using namespace testing::ext; using namespace updater_ut; using namespace updater; using namespace std; @@ -38,7 +39,7 @@ void BlockSetUnitTest::TearDown(void) cout << "TearDownTestCase" << endl; } -TEST(BlockSetUnitTest, blockset_test_001) +HWTEST_F(BlockSetUnitTest, blockset_test_001, TestSize.Level1) { cout << "Blockset ut start"; BlockSet block(std::vector {BlockPair{0, 1}}); @@ -65,7 +66,7 @@ TEST(BlockSetUnitTest, blockset_test_001) EXPECT_EQ(ret, -1); } -TEST(BlockSetUnitTest, blockset_test_002) +HWTEST_F(BlockSetUnitTest, blockset_test_002, TestSize.Level1) { cout << "Blockset ut two blocks overlap"; BlockSet block(std::vector {BlockPair{0, 1}}); @@ -77,7 +78,7 @@ TEST(BlockSetUnitTest, blockset_test_002) EXPECT_EQ(ret, false); } -TEST(BlockSetUnitTest, blockset_test_003) +HWTEST_F(BlockSetUnitTest, blockset_test_003, TestSize.Level1) { cout << "Blockset ut two blocks overlap"; std::vector buffer; @@ -86,10 +87,15 @@ TEST(BlockSetUnitTest, blockset_test_003) std::fill(buffer.begin(), buffer.end(), 0); std::string filename = "/tmp/ut_blockset"; int fd = open(filename.c_str(), O_RDWR); + if (fd < 0) { + printf("Open file failed"); + return; + } blk.WriteDataToBlock(fd, buffer); + close(fd); } -TEST(BlockSetUnitTest, blockset_test_004) +HWTEST_F(BlockSetUnitTest, blockset_test_004, TestSize.Level1) { cout << "Blockset ut two blocks overlap"; std::vector srcBuffer; @@ -102,12 +108,16 @@ TEST(BlockSetUnitTest, blockset_test_004) BlockSet::MoveBlock(srcBuffer, blk, tgtBuffer); } -TEST(BlockSetUnitTest, blockset_test_005) +HWTEST_F(BlockSetUnitTest, blockset_test_005, TestSize.Level1) { std::string hashValue = "5aa246ebe8e817740f12cc0f6e536c5ea22e5db177563a1caea5a86614275546"; std::string blockInfo = "2,20755,21031 276 2,20306,20582"; std::string cmdLine = std::string("move ") + hashValue + " " + blockInfo; int fd = open("/data/updater/updater/blocksetTest.txt", O_CREAT | O_WRONLY, S_IRWXU | S_IRWXG | S_IRWXO); + if (fd < 0) { + printf("Open file failed"); + return; + } Command *cmd = new Command(); cmd->Init(cmdLine); cmd->SetFileDescriptor(fd); @@ -121,5 +131,6 @@ TEST(BlockSetUnitTest, blockset_test_005) ret = targetBlock.WriteDiffToBlock(const_cast(*cmd), buffer, tgtBlockSize, isImgDiff); EXPECT_EQ(ret, -1); close(fd); + delete cmd; } } diff --git a/test/unittest/applypatch_test/bspatch_unittest.cpp b/test/unittest/applypatch_test/bspatch_unittest.cpp index 4a52f87f1c9b07ba8369bb153252f785aa8ca1dc..747f813fefdff9bf2cefaf80b111ea325d6c4879 100755 --- a/test/unittest/applypatch_test/bspatch_unittest.cpp +++ b/test/unittest/applypatch_test/bspatch_unittest.cpp @@ -21,6 +21,7 @@ #include "applypatch/transfer_manager.h" #include "log/log.h" +using namespace testing::ext; using namespace updater; using namespace std; @@ -48,7 +49,7 @@ void BspatchUnitTest::TearDown() cout << "Updater Unit BspatchUnitTest End!" << endl; } -TEST_F(BspatchUnitTest, bspatch_test_001) +HWTEST_F(BspatchUnitTest, bspatch_test_001, TestSize.Level1) { std::string partitionName; std::string transferName; diff --git a/test/unittest/applypatch_test/commands_unittest.cpp b/test/unittest/applypatch_test/commands_unittest.cpp index 4ff2578c2abf1ac013e42e993753d692cb9df537..809d669b486370d8f86b5146ae85a6d52b8cc480 100755 --- a/test/unittest/applypatch_test/commands_unittest.cpp +++ b/test/unittest/applypatch_test/commands_unittest.cpp @@ -21,6 +21,7 @@ #include "applypatch/command.h" #include "log/log.h" +using namespace testing::ext; using namespace updater; using namespace std; @@ -48,7 +49,7 @@ void CommandsUnitTest::TearDown() cout << "Updater Unit CommandsUnitTest End!" << endl; } -TEST_F(CommandsUnitTest, command_test_001) +HWTEST_F(CommandsUnitTest, command_test_001, TestSize.Level0) { std::string hashValue = "5aa246ebe8e817740f12cc0f6e536c5ea22e5db177563a1caea5a86614275546"; std::string blockInfo = "2,20755,21031 276 2,20306,20582"; @@ -61,9 +62,10 @@ TEST_F(CommandsUnitTest, command_test_001) sha256 = cmd->GetArgumentByPos(1); EXPECT_EQ(sha256, "5aa246ebe8e817740f12cc0f6e536c5ea22e5db177563a1caea5a86614275546"); EXPECT_EQ(cmd->GetCommandLine(), cmdLine); + delete cmd; } -TEST_F(CommandsUnitTest, command_test_002) +HWTEST_F(CommandsUnitTest, command_test_002, TestSize.Level0) { std::string hashValue = "5aa246ebe8e817740f12cc0f6e536c5ea22e5db177563a1caea5a86614275546"; std::string blockInfo = "2,20755,21031 276 2,20306,20582"; @@ -90,5 +92,6 @@ TEST_F(CommandsUnitTest, command_test_002) EXPECT_EQ(cmd->Init(cmdLine), true); cmdLine = "last 1,1"; EXPECT_EQ(cmd->Init(cmdLine), true); + delete cmd; } } // updater_ut diff --git a/test/unittest/applypatch_test/imagepatch_unittest.cpp b/test/unittest/applypatch_test/imagepatch_unittest.cpp index 361b37fdd9279feb4279c8c69f386b95f1224ec6..f58c5fd57db7eb5ea14ce2e9ad375ab4c082777a 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.cpp +++ b/test/unittest/applypatch_test/imagepatch_unittest.cpp @@ -30,6 +30,7 @@ #include "pkg_utils.h" #include "utils.h" +using namespace testing::ext; using namespace updater; namespace updater_ut { bool ImagePatchTest::ReadContentFromFile(const std::string& file, std::string &content) const @@ -52,7 +53,7 @@ bool ImagePatchTest::ReadContentFromFile(const std::string& file, std::string &c while ((n = read(fd, buffer, sizeof(buffer))) > 0) { content.append(buffer, n); } - printf("ReadContentFromFile %s %d \n", file.c_str(), n); + close(fd); return ((n == 0) ? true : false); } @@ -72,7 +73,7 @@ int ImagePatchTest::TestZipModeImagePatch() const reinterpret_cast(sourceData.data()), sourceData.size(), reinterpret_cast(patchContent.data()), patchContent.size() }; - return RunImageApplyPatch(param, "out_put_zip.zip", expectedSHA256); + return RunImageApplyPatch(param, "/data/updater/applypatch/out_put_zip.zip", expectedSHA256); } int ImagePatchTest::TestNormalModeImagePatch() const @@ -89,7 +90,7 @@ int ImagePatchTest::TestNormalModeImagePatch() const reinterpret_cast(sourceData.data()), sourceData.size(), reinterpret_cast(patchContent.data()), patchContent.size() }; - return RunImageApplyPatch(param, "out_put_zip.zip", expectedSHA256); + return RunImageApplyPatch(param, "/data/updater/diffpatch/out_put_zip.zip", expectedSHA256); } int ImagePatchTest::TestGZipModeImagePatch() const @@ -105,7 +106,7 @@ int ImagePatchTest::TestGZipModeImagePatch() const reinterpret_cast(sourceData.data()), sourceData.size(), reinterpret_cast(patchContent.data()), patchContent.size() }; - int ret = RunImageApplyPatch(param, "out_put_gzip.gzip", expectedSHA256); + int ret = RunImageApplyPatch(param, "/data/updater/applypatch/out_put_gzip.gzip", expectedSHA256); return ret; } @@ -122,29 +123,29 @@ int ImagePatchTest::TestLZ4ModeImagePatch() const reinterpret_cast(sourceData.data()), sourceData.size(), reinterpret_cast(patchContent.data()), patchContent.size() }; - RunImageApplyPatch(param, "out_put_lz4.lz4", expectedSHA256); + RunImageApplyPatch(param, "/data/updater/diffpatch/out_put_lz4.lz4", expectedSHA256); return 0; } -TEST_F(ImagePatchTest, TestZipModeImagePatch) +HWTEST_F(ImagePatchTest, TestZipModeImagePatch, TestSize.Level1) { ImagePatchTest test; EXPECT_EQ(0, test.TestZipModeImagePatch()); } -TEST_F(ImagePatchTest, TestGZipModeImagePatch) +HWTEST_F(ImagePatchTest, TestGZipModeImagePatch, TestSize.Level1) { ImagePatchTest test; EXPECT_EQ(0, test.TestGZipModeImagePatch()); } -TEST_F(ImagePatchTest, TestLZ4ModeImagePatch) +HWTEST_F(ImagePatchTest, TestLZ4ModeImagePatch, TestSize.Level1) { ImagePatchTest test; EXPECT_EQ(0, test.TestLZ4ModeImagePatch()); } -TEST_F(ImagePatchTest, TestNormalModeImagePatch) +HWTEST_F(ImagePatchTest, TestNormalModeImagePatch, TestSize.Level1) { ImagePatchTest test; EXPECT_EQ(0, test.TestNormalModeImagePatch()); diff --git a/test/unittest/applypatch_test/imagepatch_unittest.h b/test/unittest/applypatch_test/imagepatch_unittest.h index efff589cc95acb30c05964d9e79f4e2856017632..6da5f553f987e8d7f6cc47979d316a75a9f0c473 100755 --- a/test/unittest/applypatch_test/imagepatch_unittest.h +++ b/test/unittest/applypatch_test/imagepatch_unittest.h @@ -75,7 +75,7 @@ public: { mode_t mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); int fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_BINARY, mode); - EXPECT_GT(fd, 0); + EXPECT_GE(fd, 0); BlockSet targetBlk; targetBlk.ParserAndInsert({ "2", "0", "1" diff --git a/test/unittest/applypatch_test/partition_update_record_unittest.cpp b/test/unittest/applypatch_test/partition_update_record_unittest.cpp index c24d16dfde89da022d29998bd26dbe9b9ee3c875..14193d60d6c1a2dd6c7c6d5a129c466f60c533f5 100755 --- a/test/unittest/applypatch_test/partition_update_record_unittest.cpp +++ b/test/unittest/applypatch_test/partition_update_record_unittest.cpp @@ -25,6 +25,7 @@ #include "package/pkg_manager.h" #include "updater/updater.h" +using namespace testing::ext; using namespace updater; using namespace std; namespace updater_ut { @@ -51,7 +52,7 @@ void PartitionUpdateRecordUnitTest::TearDown() PartitionRecord::GetInstance().ClearRecordPartitionOffset(); } -TEST_F(PartitionUpdateRecordUnitTest, partition_record_test_001) +HWTEST_F(PartitionUpdateRecordUnitTest, partition_record_test_001, TestSize.Level1) { const std::string partitionName = "ut_partition"; bool ret = PartitionRecord::GetInstance().RecordPartitionUpdateStatus(partitionName, true); @@ -61,14 +62,14 @@ TEST_F(PartitionUpdateRecordUnitTest, partition_record_test_001) EXPECT_EQ(ret, true); } -TEST_F(PartitionUpdateRecordUnitTest, partition_record_test_002) +HWTEST_F(PartitionUpdateRecordUnitTest, partition_record_test_002, TestSize.Level1) { const std::string partitionName = "ut_partition1"; bool ret = PartitionRecord::GetInstance().IsPartitionUpdated(partitionName); EXPECT_EQ(ret, false); } -TEST_F(PartitionUpdateRecordUnitTest, partition_record_test_003) +HWTEST_F(PartitionUpdateRecordUnitTest, partition_record_test_003, TestSize.Level1) { string partitionName = "partitionName"; for (int i = 0; i < MAX_PARTITION_NUM; i++) { diff --git a/test/unittest/applypatch_test/store_unittest.cpp b/test/unittest/applypatch_test/store_unittest.cpp index 263051a764b878fb07cce23e74803b7ba623255b..237ed9e8de61895e24fd613d2837629e610fbb18 100755 --- a/test/unittest/applypatch_test/store_unittest.cpp +++ b/test/unittest/applypatch_test/store_unittest.cpp @@ -23,6 +23,7 @@ #include "log/log.h" #include "utils.h" +using namespace testing::ext; using namespace updater_ut; using namespace updater; using namespace std; @@ -38,7 +39,7 @@ void StoreUnitTest::TearDown() cout << "TearDownTestCase" << endl; } -TEST(StoreUnitTest, store_test_001) +HWTEST_F(StoreUnitTest, store_test_001, TestSize.Level1) { std::string storePath = "/data/updater/ut_test"; Store::CreateNewSpace(storePath, true); @@ -55,12 +56,9 @@ TEST(StoreUnitTest, store_test_001) EXPECT_EQ(Store::CreateNewSpace(storePath, true), 0); } -TEST(StoreUnitTest, store_test_002) +HWTEST_F(StoreUnitTest, store_test_002, TestSize.Level1) { - std::string storePath = "/data/updater/ut_test"; - Store::CreateNewSpace(storePath, true); std::vector buffer(4096, 0); - std::string filename1 = "test_file1"; - EXPECT_EQ(Store::WriteDataToStore(storePath, filename1, buffer, -1), -1); + EXPECT_EQ(Store::WriteDataToStore("", "test_file1", buffer, buffer.size()), -1); } } diff --git a/test/unittest/applypatch_test/transfer_manager_unittest.cpp b/test/unittest/applypatch_test/transfer_manager_unittest.cpp index 7f64800d685b46f9db072d696bfac5759f6479e6..1e90f090fe1d644827c4774b9e0c01d0b16c47a5 100755 --- a/test/unittest/applypatch_test/transfer_manager_unittest.cpp +++ b/test/unittest/applypatch_test/transfer_manager_unittest.cpp @@ -21,6 +21,7 @@ #include "applypatch/transfer_manager.h" #include "log/log.h" +using namespace testing::ext; using namespace updater; using namespace std; namespace updater_ut { @@ -47,7 +48,7 @@ void TransferManagerUnitTest::TearDown() cout << "Updater Unit TransferManagerUnitTest End!" << endl; } -TEST_F(TransferManagerUnitTest, transfer_manager_test_001) +HWTEST_F(TransferManagerUnitTest, transfer_manager_test_001, TestSize.Level1) { TransferManagerPtr tm = TransferManager::GetTransferManagerInstance(); std::string cmd = "zero 2,0,1"; @@ -55,7 +56,7 @@ TEST_F(TransferManagerUnitTest, transfer_manager_test_001) TransferManager::ReleaseTransferManagerInstance(tm); } -TEST_F(TransferManagerUnitTest, transfer_manager_test_002) +HWTEST_F(TransferManagerUnitTest, transfer_manager_test_002, TestSize.Level1) { TransferManagerPtr tm = TransferManager::GetTransferManagerInstance(); tm->ReloadForRetry(); diff --git a/test/unittest/diffpatch/bzip2_unittest.cpp b/test/unittest/diffpatch/bzip2_unittest.cpp index d80b1fa1354396ae0a3febed308e56e0b80a9c4f..9c367c42a35b1f928322cb94350e0d6b1d6b4334 100755 --- a/test/unittest/diffpatch/bzip2_unittest.cpp +++ b/test/unittest/diffpatch/bzip2_unittest.cpp @@ -24,6 +24,7 @@ using namespace std; using namespace hpackage; using namespace updatepatch; +using namespace testing::ext; namespace { #define LZ4_BLOCK_SIZE(blockId) (1 << (8 + (2 * (blockId)))) @@ -250,19 +251,19 @@ public: } }; -TEST_F(BZip2AdapterUnitTest, BZip2AdapterBufferTest) +HWTEST_F(BZip2AdapterUnitTest, BZip2AdapterBufferTest, TestSize.Level1) { BZip2AdapterUnitTest test; EXPECT_EQ(0, test.BZip2AdapterBufferTest()); } -TEST_F(BZip2AdapterUnitTest, BZip2AdapterAddMoreTest) +HWTEST_F(BZip2AdapterUnitTest, BZip2AdapterAddMoreTest, TestSize.Level1) { BZip2AdapterUnitTest test; EXPECT_EQ(0, test.BZip2AdapterAddMoreTest()); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForZip) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForZip, TestSize.Level1) { ZipFileInfo zipInfo {}; zipInfo.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; @@ -275,7 +276,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForZip) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.new", &zipInfo.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; @@ -287,7 +288,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_2) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_2, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; @@ -299,7 +300,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_2) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_3) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_3, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; @@ -311,7 +312,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_3) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_4) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_4, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; @@ -323,7 +324,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_4) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_5) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_5, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; @@ -336,7 +337,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4_5) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4_BLOCK; @@ -348,7 +349,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_2) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_2, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4_BLOCK; @@ -360,7 +361,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_2) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_3) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_3, TestSize.Level1) { Lz4FileInfo lz4Info {}; lz4Info.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4_BLOCK; @@ -372,7 +373,7 @@ TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_3) EXPECT_EQ(0, test.DeflateAdapterTest("../diffpatch/patchtest.test", &lz4Info.fileInfo)); } -TEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_4) +HWTEST_F(BZip2AdapterUnitTest, DeflateAdapterTestForLz4Block_4, TestSize.Level1) { DeflateAdapter adapterTest; BlockBuffer srcTestData; diff --git a/test/unittest/diffpatch/diffpatch_unittest.cpp b/test/unittest/diffpatch/diffpatch_unittest.cpp index d6a18f2a1220df6d9db6d74a889e1982f562c73a..9292e18f9f260ee0167f408bde384b130a20fc3c 100755 --- a/test/unittest/diffpatch/diffpatch_unittest.cpp +++ b/test/unittest/diffpatch/diffpatch_unittest.cpp @@ -22,6 +22,7 @@ using namespace std; using namespace hpackage; using namespace updatepatch; +using namespace testing::ext; namespace { class DiffPatchUnitTest : public testing::Test { @@ -179,7 +180,7 @@ public: } }; -TEST_F(DiffPatchUnitTest, BlockDiffPatchTest) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest( @@ -189,7 +190,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchTest) "../diffpatch/patchtest.new_1")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchFileTest) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchFileTest, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -199,7 +200,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchFileTest) "../diffpatch/patchtest.new_2")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchFileWithLimit) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchFileWithLimit, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(16, @@ -209,7 +210,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchFileWithLimit) "../diffpatch/patchtest.new_3")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -219,7 +220,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile) "../diffpatch/PatchGztest_gz_new.zip")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -229,7 +230,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File) "../diffpatch/PatchLz4test_lz4_new.lz")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_1) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_1, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -239,7 +240,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_1) "../diffpatch/ImgageDiffPatchLz4File_1_lz4_new.lz")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_2) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_2, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(1, @@ -249,7 +250,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_2) "../diffpatch/ImgageDiffPatchLz4File_1_lz4_new.lz")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_3) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_3, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -260,7 +261,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchLz4File_3) } // 测试包含一个文件时,新增一个文件 -TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -271,7 +272,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile) } // 测试使用winrar的压缩文件 -TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_1) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_1, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -282,7 +283,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_1) } // 测试包含一个文件时,文件内容不相同 -TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_2) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_2, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -293,7 +294,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_2) } // linux 上压缩,多文件测试 -TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_3) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_3, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -304,7 +305,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_3) } // linux 上压缩,超大buffer length测试 -TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_4) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_4, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest(0, @@ -314,7 +315,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchZipFile_4) "../diffpatch/ImgageDiffPatchZipFile_4_zip_new.zip")); } -TEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile2) +HWTEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile2, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.ImgageDiffPatchFileTest2(0, @@ -324,7 +325,7 @@ TEST_F(DiffPatchUnitTest, ImgageDiffPatchGzFile2) "../diffpatch/PatchGztest_gz_new.zip")); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -334,7 +335,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile) "../diffpatch/PatchGztest_gz_new.zip", true)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile_1) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile_1, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -344,7 +345,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchGzFile_1) "../diffpatch/PatchGztest_gz_new.zip", false)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -354,7 +355,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File) "../diffpatch/PatchLz4test_lz4_new.lz", true)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File_1) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File_1, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -364,7 +365,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchLz4File_1) "../diffpatch/PatchLz4test_lz4_new.lz", false)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchTest_0) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_0, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -374,7 +375,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchTest_0) "../diffpatch/patchtest.new_2", true)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchTest_1) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_1, TestSize.Level1) { DiffPatchUnitTest test; EXPECT_EQ(0, test.BlockDiffPatchTest2( @@ -384,7 +385,7 @@ TEST_F(DiffPatchUnitTest, BlockDiffPatchTest_1) "../diffpatch/patchtest.new_2", false)); } -TEST_F(DiffPatchUnitTest, BlockDiffPatchTest_2) +HWTEST_F(DiffPatchUnitTest, BlockDiffPatchTest_2, TestSize.Level1) { std::vector testDate; testDate.push_back('a'); diff --git a/test/unittest/flashd_test/flash_host_unittest.cpp b/test/unittest/flashd_test/flash_host_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e025ad56753d57a9600f254a2318a550d62170da --- /dev/null +++ b/test/unittest/flashd_test/flash_host_unittest.cpp @@ -0,0 +1,247 @@ +/* + * 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 +#include +#include +#include + +#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; +using namespace Hdc; +using namespace testing::ext; +namespace { +static std::string TEST_PARTITION_NAME = "data"; +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: + FLashHostUnitTest() {} + ~FLashHostUnitTest() {} + + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + void TestBody() {} + +public: + int TestFlashHost(uint16_t command, const std::string &cmd) + { + 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()); + return 0; + } + + 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::vector data(MAX_SIZE_IOBUF * 2); // 2 + flashHost->CommandDispatch(CMD_UPDATER_BEGIN, const_cast(data.data()), data.size()); + + std::string cmdInfo = ""; + flashHost->CommandDispatch(CMD_UPDATER_CHECK, + const_cast(reinterpret_cast(cmdInfo.data())), cmdInfo.size()); + + flashHost->CommandDispatch(CMD_UPDATER_DATA, const_cast(data.data()), data.size()); + + vector info = {0, 1, 's', 'u', 'c', 'c', 'e', 's', 's'}; + flashHost->CommandDispatch(CMD_UPDATER_FINISH, + const_cast(reinterpret_cast(info.data())), info.size()); + + 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; + } +}; + +HWTEST_F(FLashHostUnitTest, TestFlashHostErase, TestSize.Level1) +{ + FLashHostUnitTest test; + Base::SetLogLevel(LOG_LAST); // debug log print + + std::string cmdParam = "erase -f "; + cmdParam += TEST_PARTITION_NAME; + EXPECT_EQ(0, test.TestFlashHost(CMD_UPDATER_ERASE, cmdParam)); +} + +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); +} + +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 diff --git a/test/unittest/flashd_test/flash_service_unittest.cpp b/test/unittest/flashd_test/flash_service_unittest.cpp new file mode 100755 index 0000000000000000000000000000000000000000..32b63600814f8b171232436b5346562a652374e3 --- /dev/null +++ b/test/unittest/flashd_test/flash_service_unittest.cpp @@ -0,0 +1,502 @@ +/* + * 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 +#include +#include +#include + +#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 = "/data/updater/updater/updater.zip"; +static std::string TEST_FLASH_IMAGE_NAME = "/data/updater/updater/updater.zip"; + +class FLashServiceUnitTest : public testing::Test { +public: + FLashServiceUnitTest() {} + ~FLashServiceUnitTest() {} + + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} + void TestBody() {} + +public: + int TestFindAllDevice() + { + updater::LoadFstab(); + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->LoadSysDevice(); + return 0; + } + + int TestDoFlashPartition() + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoFlashPartition(TEST_FLASH_IMAGE_NAME, TEST_PARTITION_NAME); + 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; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + flash->DoErasePartition(TEST_PARTITION_NAME); + return 0; + } + + 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->DoResizeParatiton("data", 4096); // 4096 partition size + flash->DoResizeParatiton("data", 1024); // 1024 partition size + return 0; + } + + int TestFlashServiceDoPrepare(uint8_t type, const std::string &cmdParam) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterPrepare(flash.get(), type, cmdParam, TEST_UPDATER_PACKAGE_PATH); + return 0; + } + + int TestFlashServiceDoFlash(uint8_t type, const std::string &cmdParam) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterPrepare(flash.get(), type, cmdParam, TEST_UPDATER_PACKAGE_PATH); + return 0; + } + + int TestFlashServiceDoFinish(uint8_t type) + { + std::string errorMsg; + std::shared_ptr flash = std::make_shared(errorMsg); + if (flash == nullptr) { + return 1; + } + (void)flashd::DoUpdaterFinish(flash.get(), type, ""); + return 0; + } + + int TestDaemonUpdater() + { + 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->serverOrDaemon = 1; + std::shared_ptr hdcDamon = std::make_shared(hTaskInfo); + if (hdcDamon == nullptr) { + return -1; + } + + // cmd: hdc updater packagename + // check + HdcTransferBase::TransferConfig transferConfig {}; + transferConfig.functionName = "update"; + transferConfig.options = "update"; + std::string localPath = TEST_UPDATER_PACKAGE_PATH; + transferConfig.fileSize = 163884012; // 163884012 file size + 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)); + 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()); + + // begin + hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); + + 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 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 {}; + transferConfig.functionName = "flash"; + 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 = transferConfig.fileSize; + 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()); + + // begin + hdcDamon->CommandDispatch(CMD_UPDATER_BEGIN, NULL, 0); + + HdcTransferBase::TransferPayload payloadHead {}; + 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()); + // end + hdcDamon->DoTransferFinish(); + return 0; + } + + int TestHdcDaemonErase() + { + 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 erase partition + // check + std::string bufString = "erase -f "; + bufString += TEST_PARTITION_NAME; + hdcDamon->CommandDispatch(CMD_UPDATER_ERASE, reinterpret_cast(bufString.data()), bufString.size()); + return 0; + } + + int TestHdcDaemonFormat() + { + 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 format partition + // check + std::string bufString = "format -f "; + bufString += TEST_PARTITION_NAME + " -t ext4"; + hdcDamon->CommandDispatch(CMD_UPDATER_FORMAT, reinterpret_cast(bufString.data()), bufString.size()); + + return 0; + } +}; + +HWTEST_F(FLashServiceUnitTest, FLashServiceUnitTest, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFindAllDevice()); +} + +HWTEST_F(FLashServiceUnitTest, TestDaemonUpdater, TestSize.Level1) +{ + FLashServiceUnitTest test; + 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; + EXPECT_EQ(0, test.TestHdcDaemonErase()); +} + +HWTEST_F(FLashServiceUnitTest, TestHdcDaemonFormat, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestHdcDaemonFormat()); +} + +HWTEST_F(FLashServiceUnitTest, TestFindAllDevice, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFindAllDevice()); +} + +HWTEST_F(FLashServiceUnitTest, TestDoFlashPartition, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestDoFlashPartition()); +} + +HWTEST_F(FLashServiceUnitTest, TestDoFormatPartition, TestSize.Level1) +{ + FLashServiceUnitTest test; + 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) +{ + FLashServiceUnitTest test; + 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; + std::string cmdParam = "update "; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_UPDATE, cmdParam)); + + cmdParam = "flash "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FLASH, cmdParam)); + + cmdParam = "erase -f"; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_ERASE, cmdParam)); + + cmdParam = "format -f "; + cmdParam += TEST_PARTITION_NAME + " -t ext4"; + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_FORMAT, cmdParam)); + + EXPECT_EQ(0, test.TestFlashServiceDoPrepare(flashd::UPDATEMOD_MAX, cmdParam)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFlash, TestSize.Level1) +{ + FLashServiceUnitTest test; + std::string cmdParam = "update "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_UPDATE, cmdParam)); + + cmdParam = "flash "; + cmdParam += TEST_PARTITION_NAME + " "; + cmdParam += TEST_FLASH_IMAGE_NAME; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FLASH, cmdParam)); + + cmdParam = "erase -f "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_ERASE, cmdParam)); + + cmdParam = "format -f -t ext4 "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); + + cmdParam = "format -f -t f2fs "; + cmdParam += TEST_PARTITION_NAME + " "; + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_FORMAT, cmdParam)); + + EXPECT_EQ(0, test.TestFlashServiceDoFlash(flashd::UPDATEMOD_MAX, cmdParam)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashServiceDoFinish, TestSize.Level1) +{ + FLashServiceUnitTest test; + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_UPDATE)); + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_FLASH)); + EXPECT_EQ(0, test.TestFlashServiceDoFinish(flashd::UPDATEMOD_MAX)); +} + +HWTEST_F(FLashServiceUnitTest, TestFlashdMain, TestSize.Level1) +{ + const char* argv1[] = {"TestFlashdMain", "-t"}; + flashd_main(sizeof(argv1) / sizeof(char*), const_cast(argv1)); + const char *argv2[] = {"TestFlashdMain", "-u", " -l5"}; + flashd_main(sizeof(argv2)/sizeof(char*), const_cast(argv2)); +} +} // namespace \ No newline at end of file diff --git a/test/unittest/fs_manager/do_partition_unittest.cpp b/test/unittest/fs_manager/do_partition_unittest.cpp index 939b2d8a70513de452ceafa40ff961ce0bcaecbf..672b20bd02933ac34918f3882b86f7b34929a329 100755 --- a/test/unittest/fs_manager/do_partition_unittest.cpp +++ b/test/unittest/fs_manager/do_partition_unittest.cpp @@ -25,7 +25,8 @@ #include "partitions.h" #include "securec.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace std; namespace updater_ut { @@ -74,7 +75,7 @@ static void InitEmmcPartition(struct Partition &part, const std::string &partNam part.fsType = "emmc"; } -TEST_F(DoPartitionUnitTest, do_partition_test_001) +HWTEST_F(DoPartitionUnitTest, do_partition_test_001, TestSize.Level1) { PartitonList nList; int partitionIndex = 0; @@ -115,15 +116,14 @@ TEST_F(DoPartitionUnitTest, do_partition_test_001) ASSERT_GT(ret, 0); PartitonList olist; - size_t xxxPartitionStart = dataPartitionStart + XXX_PARTITION_LEN; - + size_t xxxPartitionStart = dataPartitionStart + XXX_PARTITION_LEN; InitEmmcPartition(myPaty[partitionIndex], "xxxxxx", xxxPartitionStart, XXX_PARTITION_LEN); olist.push_back(&myPaty[partitionIndex]); int ret1 = RegisterUpdaterPartitionList(nList, olist); ASSERT_EQ(ret1, 1); - char aaa[BUFFER_SIZE]; - BlockDevice myDev; + char aaa[BUFFER_SIZE] = {0}; + BlockDevice myDev {}; myDev.devPath = "xxxxxx"; myDev.specific = (void *)aaa; SetBlockDeviceMode(myDev); diff --git a/test/unittest/log_test/log_unittest.cpp b/test/unittest/log_test/log_unittest.cpp index e78a0a6ab19817b96cd77046e81d4db9c5562781..8989569e909732ee9a6a0599c833080aee1284b3 100755 --- a/test/unittest/log_test/log_unittest.cpp +++ b/test/unittest/log_test/log_unittest.cpp @@ -20,7 +20,7 @@ using namespace testing::ext; using namespace updater_ut; -using namespace updater; +using namespace updater; using namespace std; namespace updater_ut { @@ -34,7 +34,7 @@ void LogUnitTest::TearDownTestCase(void) cout << "TearDownTestCase" << endl; } -TEST(LogUnitTest, log_test_001) +HWTEST_F(LogUnitTest, log_test_001, TestSize.Level1) { SetLogLevel(ERROR); LOG(ERROR) << "this is ut"; @@ -62,7 +62,7 @@ TEST(LogUnitTest, log_test_001) } } -TEST(LogUnitTest, log_test_002) +HWTEST_F(LogUnitTest, log_test_002, TestSize.Level0) { InitUpdaterLogger("UPDATER_UT", "", "", ""); SetLogLevel(ERROR); diff --git a/test/unittest/misc_info_test/misc_info_unittest.cpp b/test/unittest/misc_info_test/misc_info_unittest.cpp index 2dc4cec786e69bda66c94d1d3b9cc3eb99f1fba7..0895b703cab520a13fc3d7190327f5bb43e0a466 100755 --- a/test/unittest/misc_info_test/misc_info_unittest.cpp +++ b/test/unittest/misc_info_test/misc_info_unittest.cpp @@ -21,7 +21,7 @@ using namespace testing::ext; using namespace updater_ut; -using namespace updater; +using namespace updater; using namespace std; namespace updater_ut { @@ -37,15 +37,16 @@ void MiscInfoUnitTest::TearDownTestCase(void) cout << "Updater Unit MiscInfoUnitTest End!" << endl; } -TEST(MiscInfoUnitTest, misc_info_test_001) +HWTEST_F(MiscInfoUnitTest, misc_info_test_001, TestSize.Level1) { auto fp = std::unique_ptr(fopen(MISC_FILE.c_str(), "wb"), fclose); EXPECT_NE(fp, nullptr); - UpdateMessage boot {}; - EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command), "boot_updater", sizeof(boot.command)), 0); - EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), - "--update_package=./updater/xxx.zip\n--retry_count=1", sizeof(boot.update)), 0); + UpdateMessage boot {}; + const std::string command1 = "boot_updater"; + EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command) - 1, command1.c_str(), command1.size()), 0); + const std::string command2 = "--update_package=./updater/xxx.zip\n--retry_count=1"; + EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update) - 1, command2.c_str(), command2.size()), 0); bool ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); diff --git a/test/unittest/mount_test/fstabapi_unittest.cpp b/test/unittest/mount_test/fstabapi_unittest.cpp index 332e5b09bfd7fe9804dbbd741c3d69b597410a85..e772ece40ac0f192a55c27160b3c4308646e4012 100755 --- a/test/unittest/mount_test/fstabapi_unittest.cpp +++ b/test/unittest/mount_test/fstabapi_unittest.cpp @@ -23,8 +23,7 @@ #include #include #include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" +#include "fs_manager/fs_manager.h" #include "fs_manager/mount.h" #include "log/log.h" #include "utils.h" @@ -52,89 +51,100 @@ void FstabApiUnitTest::SetUpTestCase(void) {} // do something at the each function end void FstabApiUnitTest::TearDownTestCase(void) {} -TEST_F(FstabApiUnitTest, ReadFstabFromFile_unitest) +HWTEST_F(FstabApiUnitTest, ReadFstabFromFile_unitest, TestSize.Level1) { - Fstab fstab; + Fstab *fstab = nullptr; const std::string fstabFile1 = "/data/fstab.updater1"; - bool ret = ReadFstabFromFile(fstabFile1, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile2 = "/data/updater/mount_unitest/ReadFstabFromFile1.fstable"; - ret = ReadFstabFromFile(fstabFile2, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile2.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile3 = "/data/updater/mount_unitest/ReadFstabFromFile2.fstable"; - ret = ReadFstabFromFile(fstabFile3, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile3.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile4 = "/data/updater/mount_unitest/ReadFstabFromFile3.fstable"; - ret = ReadFstabFromFile(fstabFile4, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile4.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile5 = "/data/updater/mount_unitest/ReadFstabFromFile4.fstable"; - ret = ReadFstabFromFile(fstabFile5, fstab); - EXPECT_FALSE(ret); + fstab = ReadFstabFromFile(fstabFile5.c_str(), false); + EXPECT_EQ(fstab, nullptr); const std::string fstabFile6 = "/data/updater/mount_unitest/ReadFstabFromFile5.fstable"; - ret = ReadFstabFromFile(fstabFile6, fstab); - EXPECT_TRUE(ret); + fstab = ReadFstabFromFile(fstabFile6.c_str(), false); + EXPECT_NE(fstab, nullptr); + ReleaseFstab(fstab); } -TEST_F(FstabApiUnitTest, FindFstabItemForPath_unitest) +HWTEST_F(FstabApiUnitTest, FindFstabItemForPath_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/FindFstabItemForPath1.fstable"; - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); - struct FstabItem* item = nullptr; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; const std::string path1 = ""; - item = FindFstabItemForPath(fstab1, path1); + item = FindFstabItemForPath(*fstab, path1.c_str()); if (item == nullptr) { SUCCEED(); } const std::string path2 = "/data"; - item = FindFstabItemForPath(fstab1, path2); + item = FindFstabItemForPath(*fstab, path2.c_str()); if (item != nullptr) { SUCCEED(); } const std::string path3 = "/data2"; - item = FindFstabItemForPath(fstab1, path3); + item = FindFstabItemForPath(*fstab, path3.c_str()); if (item == nullptr) { SUCCEED(); } const std::string path4 = "/data2/test"; - item = FindFstabItemForPath(fstab1, path4); + item = FindFstabItemForPath(*fstab, path4.c_str()); if (item != nullptr) { SUCCEED(); } + ReleaseFstab(fstab); + fstab = nullptr; } -TEST_F(FstabApiUnitTest, FindFstabItemForMountPoint_unitest) +HWTEST_F(FstabApiUnitTest, FindFstabItemForMountPoint_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/FindFstabItemForMountPoint1.fstable"; - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); - struct FstabItem* item = nullptr; + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); + FstabItem* item = nullptr; const std::string mp1 = "/data"; const std::string mp2 = "/data2"; - item = FindFstabItemForMountPoint(fstab1, mp2); + item = FindFstabItemForMountPoint(*fstab, mp2.c_str()); if (item == nullptr) { SUCCEED(); } const std::string mp3 = "/data"; - item = FindFstabItemForMountPoint(fstab1, mp3); + item = FindFstabItemForMountPoint(*fstab, mp3.c_str()); if (item != nullptr) { SUCCEED(); } + ReleaseFstab(fstab); + fstab = nullptr; } -TEST_F(FstabApiUnitTest, GetMountFlags_unitest) +HWTEST_F(FstabApiUnitTest, GetMountFlags_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/GetMountFlags1.fstable"; - Fstab fstab1; - ReadFstabFromFile(fstabFile1, fstab1); + Fstab *fstab = nullptr; + fstab = ReadFstabFromFile(fstabFile1.c_str(), false); + ASSERT_NE(fstab, nullptr); struct FstabItem* item = nullptr; const std::string mp = "/hos"; - item = FindFstabItemForMountPoint(fstab1, mp); + item = FindFstabItemForMountPoint(*fstab, mp.c_str()); if (item == nullptr) { SUCCEED(); } - std::string fsSpecificOptions; - unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions); + const int bufferSize = 512; + char fsSpecificOptions[bufferSize] = {0}; + unsigned long flags = GetMountFlags(item->mountOptions, fsSpecificOptions, bufferSize); EXPECT_EQ(flags, static_cast(MS_NOSUID | MS_NODEV | MS_NOATIME)); + ReleaseFstab(fstab); + fstab = nullptr; } } // namespace updater_ut diff --git a/test/unittest/mount_test/mount_unittest.cpp b/test/unittest/mount_test/mount_unittest.cpp index 04df3a6b07736f5e4364d80c9de9454941ad3ef2..e008ecdba0edba6476b3e119e244deaaaf59dee8 100755 --- a/test/unittest/mount_test/mount_unittest.cpp +++ b/test/unittest/mount_test/mount_unittest.cpp @@ -25,8 +25,7 @@ #include #include #include -#include "fs_manager/fstab.h" -#include "fs_manager/fstab_api.h" +#include "fs_manager/fs_manager.h" #include "fs_manager/mount.h" #include "log/log.h" #include "utils.h" @@ -60,7 +59,7 @@ void MountUnitTest::TearDownTestCase(void) rmdir("/misc"); } -TEST_F(MountUnitTest, FormatPartition_unitest) +HWTEST_F(MountUnitTest, FormatPartition_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/FormatPartition1.fstable"; LoadSpecificFstab(fstabFile1); @@ -78,7 +77,7 @@ TEST_F(MountUnitTest, FormatPartition_unitest) EXPECT_EQ(ret, -1); } -TEST_F(MountUnitTest, MountForPath_unitest) +HWTEST_F(MountUnitTest, MountForPath_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/MountForPath1.fstable"; LoadSpecificFstab(fstabFile1); @@ -99,7 +98,7 @@ TEST_F(MountUnitTest, MountForPath_unitest) EXPECT_EQ(ret, -1); } -TEST_F(MountUnitTest, UmountForPath_unitest) +HWTEST_F(MountUnitTest, UmountForPath_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/UmountForPath1.fstable"; LoadSpecificFstab(fstabFile1); @@ -114,7 +113,7 @@ TEST_F(MountUnitTest, UmountForPath_unitest) EXPECT_EQ(ret, 0); } -TEST_F(MountUnitTest, GetMountStatusForPath_unitest) +HWTEST_F(MountUnitTest, GetMountStatusForPath_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/GetMountStatusForPath1.fstable"; LoadSpecificFstab(fstabFile1); @@ -129,30 +128,7 @@ TEST_F(MountUnitTest, GetMountStatusForPath_unitest) EXPECT_EQ(ret, MountStatus::MOUNT_UMOUNTED); } -TEST_F(MountUnitTest, GetItemForMountPoint_unitest) -{ - const std::string fstabFile1 = "/data/updater/mount_unitest/GetItemForMountPoint1.fstable"; - LoadSpecificFstab(fstabFile1); - const std::string mountPoint1 = "/data"; - struct FstabItem * item = GetItemForMountPoint(mountPoint1); - if (item == nullptr) { - SUCCEED(); - } - const std::string fstabFile2 = "/data/updater/mount_unitest/GetItemForMountPoint2.fstable"; - LoadSpecificFstab(fstabFile2); - const std::string mountPoint2 = "/data2"; - item = GetItemForMountPoint(mountPoint2); - if (item == nullptr) { - SUCCEED(); - } - const std::string mountPoint3 = "/data"; - item = GetItemForMountPoint(mountPoint3); - if (item != nullptr) { - SUCCEED(); - } -} - -TEST_F(MountUnitTest, SetupPartitions_unitest) +HWTEST_F(MountUnitTest, SetupPartitions_unitest, TestSize.Level1) { const std::string fstabFile1 = "/data/updater/mount_unitest/SetupPartitions1.fstable"; LoadSpecificFstab(fstabFile1); @@ -164,7 +140,7 @@ TEST_F(MountUnitTest, SetupPartitions_unitest) EXPECT_EQ(ret, 0); } -TEST_F(MountUnitTest, GetBlockDeviceByMountPoint_unitest) +HWTEST_F(MountUnitTest, GetBlockDeviceByMountPoint_unitest, TestSize.Level1) { LoadFstab(); const std::string fstabFile1 = "/data/updater/mount_unitest/GetBlockDeviceByMountPoint1.fstable"; @@ -177,8 +153,9 @@ TEST_F(MountUnitTest, GetBlockDeviceByMountPoint_unitest) std::cout << "Cannot re-mount vendor\n"; } auto ret = open(tmpPath.c_str(), O_RDONLY|O_CREAT|O_TRUNC, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); - if (ret != 0 && errno != EEXIST) { + if (ret < 0) { std::cout << "Cannot open \"/vendor/etc/fstab.updater\" file: " << errno << "\n"; + return; } close(ret); LoadFstab(); diff --git a/test/unittest/package/package_unittest.cpp b/test/unittest/package/package_unittest.cpp index c1d91fba132ec42e98ae87beb6f45887c57c0f19..5031c3e02f240de75df34e57be0eb0cd8b7b4d3a 100755 --- a/test/unittest/package/package_unittest.cpp +++ b/test/unittest/package/package_unittest.cpp @@ -30,6 +30,7 @@ using namespace std; using namespace hpackage; using namespace updater; +using namespace testing::ext; namespace { class PackageUnitTest : public PkgTest { @@ -37,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; @@ -47,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; @@ -73,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); @@ -87,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++) { @@ -103,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++) { @@ -145,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() @@ -169,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() @@ -177,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++) { @@ -196,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; } @@ -207,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++) { @@ -219,7 +224,7 @@ public: return ret; } - int TestVersifyUpgradePackage() + int TestVerifyUpgradePackage() { int ret = TestPackagePack(); constexpr size_t digestSize = 32; @@ -227,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 TestVersifyZipWithCallback() + int TestVerifyZipWithCallback() { - int32_t ret = TestVersifyZip(); + 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 TestVersifyZip() + 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; @@ -259,15 +264,17 @@ 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; } - int TestVersifyLz4() + int TestVerifyLz4() { int32_t ret = TestLz4PkgCompress(); EXPECT_EQ(ret, 0); @@ -278,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; } @@ -308,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); @@ -318,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; } @@ -354,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; } @@ -402,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) @@ -410,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++) { @@ -439,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; @@ -450,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); @@ -559,101 +568,116 @@ public: } }; -TEST_F(PackageUnitTest, TestPackage) +HWTEST_F(PackageUnitTest, TestPackage, TestSize.Level1) +{ + PackageUnitTest test; + 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.TestPackagePack()); - EXPECT_EQ(0, test.TestPackageUnpack()); + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA256)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA256)); } -TEST_F(PackageUnitTest, TestZipPackage) +HWTEST_F(PackageUnitTest, TestZipPackage384, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestZipPkgCompress()); - EXPECT_EQ(0, test.TestZipPkgDecompress()); + EXPECT_EQ(0, test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA384)); } -TEST_F(PackageUnitTest, TestLz4Package) +HWTEST_F(PackageUnitTest, TestLz4Package, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestLz4PkgCompress()); EXPECT_EQ(0, test.TestLz4PkgDecompress()); } -TEST_F(PackageUnitTest, TestLz4PackageBlock) +HWTEST_F(PackageUnitTest, TestLz4PackageBlock, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestLz4PkgCompressBlock()); EXPECT_EQ(0, test.TestLz4PkgDecompress()); } -TEST_F(PackageUnitTest, TestCombinePkg) +HWTEST_F(PackageUnitTest, TestCombinePkg, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestCombinePkgUnpack()); } -TEST_F(PackageUnitTest, TestVersifyUpgradePackage) +HWTEST_F(PackageUnitTest, TestVerifyUpgradePackage, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVersifyUpgradePackage()); + EXPECT_EQ(0, test.TestVerifyUpgradePackage()); } -TEST_F(PackageUnitTest, TestVersifyZipWithCallback) +HWTEST_F(PackageUnitTest, TestVerifyZipWithCallback, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVersifyZipWithCallback()); + EXPECT_EQ(0, test.TestVerifyZipWithCallback()); } -TEST_F(PackageUnitTest, TestVersifyZip) +HWTEST_F(PackageUnitTest, TestVerifyZip, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVersifyZip()); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA384)); + EXPECT_EQ(0, test.TestVerifyZip(PKG_DIGEST_TYPE_SHA256)); } -TEST_F(PackageUnitTest, TestVersifyLz4) { +HWTEST_F(PackageUnitTest, TestVerifyLz4, TestSize.Level1) { PackageUnitTest test; - EXPECT_EQ(0, test.TestVersifyLz4()); + EXPECT_EQ(0, test.TestVerifyLz4()); } -TEST_F(PackageUnitTest, TestInterfaceLz4) +HWTEST_F(PackageUnitTest, TestInterfaceLz4, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestInterfaceLz4()); } -TEST_F(PackageUnitTest, TestInterfaceZip) +HWTEST_F(PackageUnitTest, TestInterfaceZip, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestInterfaceZip()); } -TEST_F(PackageUnitTest, TestInvalidCreatePackage) +HWTEST_F(PackageUnitTest, TestInvalidCreatePackage, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestInvalidCreatePackage()); } -TEST_F(PackageUnitTest, TestGZipPkg) +HWTEST_F(PackageUnitTest, TestGZipPkg, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestGZipPkgCompress()); EXPECT_EQ(0, test.TestGZipPkgDecompressAll()); } -TEST_F(PackageUnitTest, TestSecondLoadPackage) +HWTEST_F(PackageUnitTest, TestSecondLoadPackage, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestSecondLoadPackage()); } -TEST_F(PackageUnitTest, TestL1PackagePack) +HWTEST_F(PackageUnitTest, TestL1PackagePack, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestL1PackagePack()); } -TEST_F(PackageUnitTest, TestL1PackagePackSha384) +HWTEST_F(PackageUnitTest, TestL1PackagePackSha384, TestSize.Level1) { PackageUnitTest test; EXPECT_EQ(0, test.TestL1PackagePackSha384()); diff --git a/test/unittest/package/pkg_algo_unittest.cpp b/test/unittest/package/pkg_algo_unittest.cpp index ba5a86f40f5dcf219d0e9cb7d975f08926847d32..43836721c6108b3ebcb56a5b0859abd077f2990c 100755 --- a/test/unittest/package/pkg_algo_unittest.cpp +++ b/test/unittest/package/pkg_algo_unittest.cpp @@ -28,6 +28,7 @@ using namespace std; using namespace hpackage; using namespace updater; +using namespace testing::ext; namespace { constexpr size_t BUFFER_LEN = 10; @@ -130,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; @@ -140,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; @@ -151,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); @@ -217,7 +218,7 @@ private: }; }; -TEST_F(PkgAlgoUnitTest, TestHash256Digest) +HWTEST_F(PkgAlgoUnitTest, TestHash256Digest, TestSize.Level1) { PkgAlgoUnitTest test; EXPECT_EQ(0, test.TestCrcDigest()); @@ -225,35 +226,44 @@ TEST_F(PkgAlgoUnitTest, TestHash256Digest) EXPECT_EQ(0, test.TestHash384Digest()); } -TEST_F(PkgAlgoUnitTest, TestRsaSignVerify) +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)); } -TEST_F(PkgAlgoUnitTest, TestEccSignVerify) +HWTEST_F(PkgAlgoUnitTest, TestRsaSignVerify384, 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_RSA, + "rsa_private_key384.pem", "signing_cert384.crt", PKG_DIGEST_TYPE_SHA384)); } -TEST_F(PkgAlgoUnitTest, TestEccUserPackage) +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", PKG_DIGEST_TYPE_SHA256)); +} + +HWTEST_F(PkgAlgoUnitTest, TestEccUserPackage, TestSize.Level1) { PkgAlgoUnitTest test; EXPECT_EQ(0, test.TestEccUserPackage(PKG_SIGN_METHOD_ECDSA, "ecc/prime256v1-key.pem", "ecc/signing_cert.crt")); } -TEST_F(PkgAlgoUnitTest, TestInvalid) +HWTEST_F(PkgAlgoUnitTest, TestInvalid, TestSize.Level1) { PkgAlgoUnitTest test; EXPECT_EQ(0, test.TestInvalidParam()); } -TEST_F(PkgAlgoUnitTest, TestPkgAlgoDeflate) +HWTEST_F(PkgAlgoUnitTest, TestPkgAlgoDeflate, TestSize.Level1) { - ZipFileInfo info; + ZipFileInfo info {}; PkgAlgoDeflate a1(info); - Lz4FileInfo config; + Lz4FileInfo config {}; PkgAlgorithmLz4 a2(config); PkgAlgorithmBlockLz4 a3(config); VerifyAlgorithm a4("aa", 0); diff --git a/test/unittest/package/pkg_manager_unittest.cpp b/test/unittest/package/pkg_manager_unittest.cpp index 2f68ebe9ebe938ec88cf3f2e0142b49a34b59f2d..dcbf120d6ee11d29fef978d8c1567cc33f874f88 100755 --- a/test/unittest/package/pkg_manager_unittest.cpp +++ b/test/unittest/package/pkg_manager_unittest.cpp @@ -34,6 +34,7 @@ using namespace std; using namespace hpackage; using namespace updater; +using namespace testing::ext; namespace { constexpr auto WINDOWBITS = -15; // 32kb window; negative to indicate a raw stream. @@ -51,7 +52,8 @@ constexpr int32_t ZIP_MAX_LEVEL = 9; class TestPkgStream : public PkgStreamImpl { public: - explicit TestPkgStream(std::string fileName) : PkgStreamImpl(fileName) {} + explicit TestPkgStream(PkgManager::PkgManagerPtr pkgManager, std::string fileName) + : PkgStreamImpl(pkgManager, fileName) {} virtual ~TestPkgStream() {} int32_t Read(const PkgBuffer &buff, size_t start, size_t size, size_t &readLen) override @@ -72,7 +74,7 @@ public: } const std::string GetFileName() const override { - return 0; + return ""; } size_t GetFileLength() override { @@ -135,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; } @@ -151,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; } @@ -162,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; } @@ -175,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; @@ -187,7 +189,10 @@ public: // 测试文件提取 PkgManager::StreamPtr outStream = nullptr; const FileInfo *info = pkgManager_->GetFileInfo(components[0]); - EXPECT_NE(info, nullptr); + if (info == nullptr) { + return PKG_INVALID_FILE; + } + ret = pkgManager_->CreatePkgStream(outStream, components[0], info->unpackedSize, PkgStream::PkgStreamType_MemoryMap); EXPECT_NE(outStream, nullptr); @@ -225,7 +230,7 @@ public: int TestPkgStreamImpl() { std::string path = TEST_PATH_TO + testCombinePkgName; - std::unique_ptr stream = std::make_unique(path); + std::unique_ptr stream = std::make_unique(pkgManager_, path); EXPECT_NE(stream, nullptr); constexpr size_t buffSize = 10; uint8_t buff[buffSize]; @@ -253,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; @@ -265,7 +270,9 @@ public: // 测试文件提取 PkgManager::StreamPtr outStream = nullptr; const FileInfo *info = pkgManager_->GetFileInfo(components[0]); - EXPECT_NE(info, nullptr); + if (info == nullptr) { + return PKG_INVALID_FILE; + } ret = pkgManager_->CreatePkgStream(outStream, TEST_PATH_TO + components[0], info->unpackedSize, PkgStream::PkgStreamType_Write); @@ -290,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; @@ -302,7 +309,10 @@ public: // 测试文件提取 PkgManager::StreamPtr outStream = nullptr; const FileInfo *info = pkgManager_->GetFileInfo(components[0]); - EXPECT_NE(info, nullptr); + if (info == nullptr) { + return PKG_INVALID_FILE; + } + ret = pkgManager_->CreatePkgStream(outStream, components[0], TestStreamProcess, this); EXPECT_NE(outStream, nullptr); @@ -333,7 +343,7 @@ public: { std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; - auto stream = std::make_unique(testPackageName, nullptr, 0); + auto stream = std::make_unique(pkgManager_, testPackageName, nullptr, 0); size_t start = 0; size_t readLen = 0; size_t bufferSize = 10; @@ -394,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; } @@ -408,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; } @@ -430,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; } @@ -453,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; } @@ -477,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; } @@ -489,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; } @@ -538,7 +548,7 @@ public: [&](hpackage::PkgManager::StreamPtr stream) { pkgManager_->ClosePkgStream(stream); }); - PKG_CHECK(outStream != nullptr, return -1, "Can not create stream "); + PKG_CHECK(outStream != nullptr, close(fd); return -1, "Can not create stream "); void* mappedData = mmap(nullptr, (size_t)fileSize, PROT_READ, MAP_SHARED, fd, 0); PKG_CHECK(mappedData != MAP_FAILED, close(fd); return -2, "Can not mmap "); @@ -605,9 +615,10 @@ public: std::string testFileName = TEST_PATH_FROM + "../applypatch/TestDecompressGzip.new.gz"; size_t fileSize = GetFileSize(testFileName); size_t uncompressedDataSize = 1024; - int32_t fd = open(testFileName.c_str(), O_RDWR); - EXPECT_GT(fd, 0); - + int fd = open(testFileName.c_str(), O_RDWR); + if (fd < 0) { + return -1; + } uncompressedData.resize(uncompressedDataSize); PkgManager::StreamPtr stream = nullptr; pkgManager_->CreatePkgStream(stream, "Gzip", @@ -629,7 +640,7 @@ public: [&](hpackage::PkgManager::StreamPtr stream) { pkgManager_->ClosePkgStream(stream); }); - PKG_CHECK(outStream != nullptr, return -1, "Can not create stream "); + PKG_CHECK(outStream != nullptr, close(fd); return -1, "Can not create stream "); void* mappedData = mmap(nullptr, (size_t)fileSize, PROT_READ, MAP_SHARED, fd, 0); PKG_CHECK(mappedData != MAP_FAILED, close(fd); return -2, "Can not mmap "); @@ -695,7 +706,7 @@ public: } }; -TEST_F(PkgMangerTest, TestGZipBuffer) +HWTEST_F(PkgMangerTest, TestGZipBuffer, TestSize.Level1) { PkgMangerTest test; hpackage::ZipFileInfo zipInfo; @@ -714,7 +725,7 @@ TEST_F(PkgMangerTest, TestGZipBuffer) uncompressedData.clear(); } -TEST_F(PkgMangerTest, TestLz4Buffer) +HWTEST_F(PkgMangerTest, TestLz4Buffer, TestSize.Level1) { PkgMangerTest test; hpackage::Lz4FileInfo lz4Info; @@ -734,7 +745,7 @@ TEST_F(PkgMangerTest, TestLz4Buffer) uncompressedData.clear(); } -TEST_F(PkgMangerTest, TestInvalidCreatePackage) +HWTEST_F(PkgMangerTest, TestInvalidCreatePackage, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestPackagePack()); @@ -742,49 +753,49 @@ TEST_F(PkgMangerTest, TestInvalidCreatePackage) EXPECT_EQ(0, test.TestPackagePackParamInvalid()); } -TEST_F(PkgMangerTest, TestPkgStreamImpl) +HWTEST_F(PkgMangerTest, TestPkgStreamImpl, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestPkgStreamImpl()); } -TEST_F(PkgMangerTest, TestPkgMmmapStream) +HWTEST_F(PkgMangerTest, TestPkgMmmapStream, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestPkgMmmapStream()); } -TEST_F(PkgMangerTest, TestPkgFileStream) +HWTEST_F(PkgMangerTest, TestPkgFileStream, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestPkgFileStream()); } -TEST_F(PkgMangerTest, TestPkgProcessStream) +HWTEST_F(PkgMangerTest, TestPkgProcessStream, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestPkgProcessStream()); } -TEST_F(PkgMangerTest, TestInvalidStream) +HWTEST_F(PkgMangerTest, TestInvalidStream, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestInvalidStream()); } -TEST_F(PkgMangerTest, TestRead) +HWTEST_F(PkgMangerTest, TestRead, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestRead()); } -TEST_F(PkgMangerTest, TestCheckFile) +HWTEST_F(PkgMangerTest, TestCheckFile, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestCheckFile()); } -TEST_F(PkgMangerTest, TestCreatePackageFail) +HWTEST_F(PkgMangerTest, TestCreatePackageFail, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestCreatePackageInvalidFile()); @@ -794,7 +805,7 @@ TEST_F(PkgMangerTest, TestCreatePackageFail) EXPECT_EQ(0, test.TestZipPackageInvalidFile()); } -TEST_F(PkgMangerTest, TestLoadPackageFail) +HWTEST_F(PkgMangerTest, TestLoadPackageFail, TestSize.Level1) { PkgMangerTest test; EXPECT_EQ(0, test.TestLoadPackageFail()); diff --git a/test/unittest/package/pkg_package_unittest.cpp b/test/unittest/package/pkg_package_unittest.cpp index f1ad1d299fa8d61c5265ac5f0a7879333171a3c8..56578540dd23b534f4bb7559fec13ed38e167240 100755 --- a/test/unittest/package/pkg_package_unittest.cpp +++ b/test/unittest/package/pkg_package_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace updater; +using namespace testing::ext; namespace { constexpr uint32_t MAX_FILE_NAME = 256; @@ -40,7 +41,8 @@ constexpr uint32_t END_CENTRAL_SIGNATURE = 0x06054b50; class TestFile : public PkgFile { public: - explicit TestFile(PkgStreamPtr stream) : PkgFile(stream, PKG_TYPE_MAX) {} + explicit TestFile(PkgManager::PkgManagerPtr pkgManager, PkgStreamPtr stream) + : PkgFile(pkgManager, stream, PKG_TYPE_MAX) {} virtual ~TestFile() {} @@ -77,7 +79,7 @@ public: std::string packagePath = TEST_PATH_TO; packagePath += testPackageName; int ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); - auto file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + auto file = std::make_unique(pkgManager_, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); constexpr uint32_t lz4NodeId = 100; auto entry = std::make_unique(file.get(), lz4NodeId); @@ -101,7 +103,8 @@ public: packagePath += testPackageName; int ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); FileInfo fileInfo; - std::unique_ptr file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr file = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); ret = file->AddEntry(&fileInfo, PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_EQ(ret, 0); @@ -121,7 +124,8 @@ public: packagePath += testPackageName; pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); EXPECT_NE(stream, nullptr); - std::unique_ptr file = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr file = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(file, nullptr); std::unique_ptr entry = std::make_unique(file.get(), zipNodeId); EXPECT_NE(entry, nullptr); @@ -136,24 +140,15 @@ public: sizeof(CentralDirEntry) + offsetWord + offset4Words; std::vector buff(buffLen); CentralDirEntry* centralDir = (CentralDirEntry *)buff.data(); + (void)memset_s(centralDir, sizeof(CentralDirEntry), 0, sizeof(CentralDirEntry)); centralDir->signature = CENTRAL_SIGNATURE; - centralDir->versionMade = 0; - centralDir->versionNeeded = 0; - centralDir->flags = 0; centralDir->compressionMethod = PKG_COMPRESS_METHOD_ZIP; - centralDir->crc = 0; - centralDir->modifiedDate = 0; - centralDir->modifiedTime = 0; centralDir->compressedSize = UINT_MAX; centralDir->uncompressedSize = UINT_MAX; centralDir->nameSize = name.length(); centralDir->extraSize = extraSize; - centralDir->commentSize = 0; - centralDir->diskNumStart = 0; - centralDir->internalAttr = 0; - centralDir->externalAttr = 0; - centralDir->localHeaderOffset = 0; - EXPECT_EQ(memcpy_s(buff.data() + sizeof(CentralDirEntry), name.length(), name.c_str(), name.length()), 0); + int ret = memcpy_s(buff.data() + sizeof(CentralDirEntry), name.length(), name.c_str(), name.length()); + EXPECT_EQ(ret, 0); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length(), 1); WriteLE16(buff.data() + sizeof(CentralDirEntry) + name.length() + offsetHalfWord, offset4Words); size_t giantNumber = 100000; @@ -213,7 +208,8 @@ public: sizeof(endDir), &endDir, sizeof(endDir)), 0); - std::unique_ptr zipFile = std::make_unique(PkgStreamImpl::ConvertPkgStream(stream)); + std::unique_ptr zipFile = std::make_unique(pkgManager_, + PkgStreamImpl::ConvertPkgStream(stream)); EXPECT_NE(zipFile, nullptr); std::vector components; int ret = zipFile->LoadPackage(components); @@ -222,25 +218,25 @@ public: } }; -TEST_F(PkgPackageTest, TestPkgFile) +HWTEST_F(PkgPackageTest, TestPkgFile, TestSize.Level1) { PkgPackageTest test; EXPECT_EQ(0, test.TestPkgFile()); } -TEST_F(PkgPackageTest, TestPkgFileInvalid) +HWTEST_F(PkgPackageTest, TestPkgFileInvalid, TestSize.Level1) { PkgPackageTest test; EXPECT_EQ(0, test.TestPkgFileInvalid()); } -TEST_F(PkgPackageTest, TestBigZip) +HWTEST_F(PkgPackageTest, TestBigZip, TestSize.Level1) { PkgPackageTest test; EXPECT_EQ(0, test.TestBigZipEntry()); } -TEST_F(PkgPackageTest, TestBigZipFile) +HWTEST_F(PkgPackageTest, TestBigZipFile, TestSize.Level1) { PkgPackageTest test; EXPECT_EQ(0, test.TestBigZipFile()); diff --git a/test/unittest/package/pkg_test.h b/test/unittest/package/pkg_test.h index badd45dfda798c01f6cdda3c27653536f7511604..315cb4203ac6d46442075465e4232eaf1fba5a72 100755 --- a/test/unittest/package/pkg_test.h +++ b/test/unittest/package/pkg_test.h @@ -70,7 +70,6 @@ protected: int32_t BuildFileDigest(uint8_t &digest, size_t size, const std::string &packagePath) { - pkgManager_ = static_cast(PkgManager::GetPackageInstance()); PkgManager::StreamPtr stream = nullptr; int32_t ret = pkgManager_->CreatePkgStream(stream, packagePath, 0, PkgStream::PkgStreamType_Read); PKG_CHECK(ret == 0, return ret, "Create input stream fail %s", packagePath.c_str()); @@ -118,6 +117,7 @@ protected: EXPECT_EQ(ret, 0); manager->ClosePkgStream(outStream); const FileInfo *info = manager->GetFileInfo(components[i]); + ASSERT_NE(info, nullptr); if (info->packMethod == PKG_COMPRESS_METHOD_NONE) { const ComponentInfo* compInfo = (const ComponentInfo*)manager->GetFileInfo(components[i]); if (compInfo != nullptr) { @@ -141,7 +141,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); @@ -158,9 +158,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/script/basic_instruction_unittest.cpp b/test/unittest/script/basic_instruction_unittest.cpp index eb1e9278038c2c6a348db812c2dd6d3d69490b12..6a81386dafafa8cda37cbf898504a0ba20c6eaa1 100755 --- a/test/unittest/script/basic_instruction_unittest.cpp +++ b/test/unittest/script/basic_instruction_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; namespace { class BasicInstructionUnittest : public ::testing::Test { @@ -50,7 +51,7 @@ protected: void TestBody() {} }; -TEST_F(BasicInstructionUnittest, TestBasicInstructionRegisterCmd) +HWTEST_F(BasicInstructionUnittest, TestBasicInstructionRegisterCmd, TestSize.Level1) { BasicInstructionUnittest test; EXPECT_EQ(0, test.TestBasicInstructionRegisterCmd()); diff --git a/test/unittest/script/script_instruction_unittest.cpp b/test/unittest/script/script_instruction_unittest.cpp index af132cf1213a7b3bc9ab5be007c84eaf6ab460c6..89f8aa72874f5af5d5db9619b473a8121c4fc8e8 100755 --- a/test/unittest/script/script_instruction_unittest.cpp +++ b/test/unittest/script/script_instruction_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; namespace { class ScriptInstructionUnitTest : public ::testing::Test { @@ -49,7 +50,7 @@ protected: void TestBody() {} }; -TEST_F(ScriptInstructionUnitTest, TestScriptInstruction) +HWTEST_F(ScriptInstructionUnitTest, TestScriptInstruction, TestSize.Level1) { ScriptInstructionUnitTest test; EXPECT_EQ(0, test.TestScriptInstruction()); diff --git a/test/unittest/script/script_interpreter_unittest.cpp b/test/unittest/script/script_interpreter_unittest.cpp index 22e2df2ea5ccb9fe69431f395cccff85c036ca1e..29081914d7244508c9e76a6a1e6feccde5a4e4c6 100755 --- a/test/unittest/script/script_interpreter_unittest.cpp +++ b/test/unittest/script/script_interpreter_unittest.cpp @@ -31,6 +31,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; namespace { class ScriptInterpreterUnitTest : public ::testing::Test { @@ -100,15 +101,15 @@ public: { std::unique_ptr funcContext = std::make_unique(); int intValue = 100; - int ret = funcContext->PushParam(intValue); + int ret1 = funcContext->PushParam(intValue); float floatValue = 100.0; - ret |= funcContext->PushParam(floatValue); + int ret2 = funcContext->PushParam(floatValue); std::string str = std::string("333333333"); - ret |= funcContext->PushParam(str); - EXPECT_EQ(0, ret); + int ret3 = funcContext->PushParam(str); + EXPECT_EQ(0, ret1 || ret2 || ret3); int32_t outOfIndex = 3; - ret = funcContext->GetParamType(outOfIndex); + int ret = funcContext->GetParamType(outOfIndex); EXPECT_EQ(UScriptContext::PARAM_TYPE_INVALID, ret); return 0; } @@ -191,37 +192,37 @@ protected: void TestBody() {} }; -TEST_F(ScriptInterpreterUnitTest, TestScriptInterpreterScriptValue) +HWTEST_F(ScriptInterpreterUnitTest, TestScriptInterpreterScriptValue, TestSize.Level0) { ScriptInterpreterUnitTest test; EXPECT_EQ(0, test.TestScriptInterpreterScriptValue()); } -TEST_F(ScriptInterpreterUnitTest, TestScriptInstructionContext) +HWTEST_F(ScriptInterpreterUnitTest, TestScriptInstructionContext, TestSize.Level0) { ScriptInterpreterUnitTest test; EXPECT_EQ(0, test.TestScriptInstructionContext()); } -TEST_F(ScriptInterpreterUnitTest, TestIntegerValueComputer) +HWTEST_F(ScriptInterpreterUnitTest, TestIntegerValueComputer, TestSize.Level0) { ScriptInterpreterUnitTest test; EXPECT_EQ(0, test.TestIntegerValueComputer()); } -TEST_F(ScriptInterpreterUnitTest, TestFloatValueComputer) +HWTEST_F(ScriptInterpreterUnitTest, TestFloatValueComputer, TestSize.Level0) { ScriptInterpreterUnitTest test; EXPECT_EQ(0, test.TestFloatValueComputer()); } -TEST_F(ScriptInterpreterUnitTest, TestStringValueComputer) +HWTEST_F(ScriptInterpreterUnitTest, TestStringValueComputer, TestSize.Level0) { ScriptInterpreterUnitTest test; EXPECT_EQ(0, test.TestStringValueComputer()); } -TEST_F(ScriptInterpreterUnitTest, SomeDestructor) +HWTEST_F(ScriptInterpreterUnitTest, SomeDestructor, TestSize.Level0) { IntegerValue a1(0); FloatValue a2(0.0); diff --git a/test/unittest/script/script_unittest.cpp b/test/unittest/script/script_unittest.cpp index 8fe48aa347a9a4a4ca1f58843e8fc434a62d9e62..f32fa7e6050d5fa6fc769ffbaff13c527995013b 100755 --- a/test/unittest/script/script_unittest.cpp +++ b/test/unittest/script/script_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; namespace { constexpr int32_t SCRIPT_TEST_PRIORITY_NUM = 3; @@ -71,6 +72,7 @@ public: virtual void DestoryInstructionInstance(UScriptInstructionPtr& instr) { delete instr; + instr = nullptr; } TestScriptInstructionFactory() {} virtual ~TestScriptInstructionFactory() {} @@ -107,8 +109,8 @@ public: { return isRetry; } -private: UScriptInstructionFactory *factory_ = nullptr; +private: bool isRetry = false; }; @@ -280,7 +282,7 @@ private: std::string testPackageName = "test_package.bin"; }; -TEST_F(UScriptTest, TestUscriptExecute) +HWTEST_F(UScriptTest, TestUscriptExecute, TestSize.Level1) { UScriptTest test; EXPECT_EQ(0, test.TestUscriptExecute()); diff --git a/test/unittest/script/threadpool_unittest.cpp b/test/unittest/script/threadpool_unittest.cpp index 55a0344ea671b9bef1c3118f1d21acecdcbaa769..7b9c38668fad05313fb05a4f67b30bb9573a8ef8 100755 --- a/test/unittest/script/threadpool_unittest.cpp +++ b/test/unittest/script/threadpool_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; namespace { const int32_t MAX_TASK_NUMBER = 5; @@ -71,7 +72,7 @@ private: ThreadPool* threadPool_; }; -TEST_F(ThreadPoolUnitTest, TestThreadPoolCreate) +HWTEST_F(ThreadPoolUnitTest, TestThreadPoolCreate, TestSize.Level0) { ThreadPoolUnitTest test; for (size_t i = 0; i < MAX_TASK_NUMBER * 2; i++) { @@ -79,7 +80,7 @@ TEST_F(ThreadPoolUnitTest, TestThreadPoolCreate) } } -TEST_F(ThreadPoolUnitTest, TestThreadOneCreate) +HWTEST_F(ThreadPoolUnitTest, TestThreadOneCreate, TestSize.Level0) { ThreadPoolUnitTest test; EXPECT_EQ(0, test.TestThreadPoolCreate(1)); 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/services/include/sparse_image/sparse_image_api.h b/test/unittest/test_data/updater/test.img old mode 100644 new mode 100755 similarity index 58% rename from services/include/sparse_image/sparse_image_api.h rename to test/unittest/test_data/updater/test.img index 210541e4e01ad6ce316f6261fda9a1ec2e700324..ab7bd1d2d7e84e832b328c39173fd49e321a6188 --- a/services/include/sparse_image/sparse_image_api.h +++ b/test/unittest/test_data/updater/test.img @@ -1,26 +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. - */ - -#ifndef UPDATER_SPARSE_IMAGE_API_H -#define UPDATER_SPARSE_IMAGE_API_H -namespace updater { -// SparseImage structure is an internal structure of libsparseimage -// Just declare it here. -struct SparseImage; -struct SparseImage *CreateSparseImageFromBuffer(char *buff); -void DeallocateSparseImage(struct SparseImage *si); -int SparseImageRestore(int fd, struct SparseImage *si); -} // namespace updater -#endif // UPDATER_SPARSE_IMAGE_API_H +/* + * 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/update_image_block_test.cpp b/test/unittest/updater_binary/update_image_block_test.cpp index 8d771d0ee7255b72927231c3a7f20f7fb31839d4..148976e489bb2b8d26d510f680f8edad9b4a24b8 100755 --- a/test/unittest/updater_binary/update_image_block_test.cpp +++ b/test/unittest/updater_binary/update_image_block_test.cpp @@ -38,7 +38,8 @@ #include "update_processor.h" #include "utils.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace uscript; using namespace std; using namespace hpackage; @@ -68,7 +69,7 @@ void UpdateImageBlockTest::TearDown() cout << "TearDownTestCase" << endl; } -TEST(UpdateImageBlockTest, update_image_block_test_001) +HWTEST_F(UpdateImageBlockTest, update_image_block_test_001, TestSize.Level1) { LoadSpecificFstab("/data/updater/applypatch/etc/fstab.ut.updater"); string devPath = GetBlockDeviceByMountPoint("/vendortest1"); @@ -91,7 +92,7 @@ TEST(UpdateImageBlockTest, update_image_block_test_001) PkgManager::ReleasePackageInstance(pkgManager); } -TEST(UpdateImageBlockTest, update_image_block_test_002) +HWTEST_F(UpdateImageBlockTest, update_image_block_test_002, TestSize.Level1) { LoadSpecificFstab("/data/updater/applypatch/etc/fstab.ut.updater"); string devPath = GetBlockDeviceByMountPoint("/vendortest"); diff --git a/test/unittest/updater_binary/update_partitions_unittest.cpp b/test/unittest/updater_binary/update_partitions_unittest.cpp index 4b5c80c0fde18d94ddc48e38cc575aec68a3b0a8..f89e2045da9ca4f87bb31964fcc261243d95b590 100755 --- a/test/unittest/updater_binary/update_partitions_unittest.cpp +++ b/test/unittest/updater_binary/update_partitions_unittest.cpp @@ -30,6 +30,7 @@ #include "utils.h" using namespace updater; +using namespace testing::ext; using namespace uscript; using namespace std; using namespace hpackage; @@ -51,7 +52,7 @@ void UpdatePartitionsUnitTest::SetUpTestCase(void) {} // do something at the each function end void UpdatePartitionsUnitTest::TearDownTestCase(void) {} -TEST_F(UpdatePartitionsUnitTest, UpdatePartitions_Unitest01) +HWTEST_F(UpdatePartitionsUnitTest, UpdatePartitions_Unitest01, TestSize.Level1) { const string packagePath = "/data/updater/updater/parts/updaterpart01.zip"; PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); @@ -74,7 +75,7 @@ TEST_F(UpdatePartitionsUnitTest, UpdatePartitions_Unitest01) EXPECT_EQ(partRet, USCRIPT_SUCCESS); } -TEST_F(UpdatePartitionsUnitTest, UpdatePartitions_Unitest02) +HWTEST_F(UpdatePartitionsUnitTest, UpdatePartitions_Unitest02, TestSize.Level1) { const string packagePath = "/data/updater/updater/parts/updaterpart02.zip"; PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); diff --git a/test/unittest/updater_binary/update_processor_unittest.cpp b/test/unittest/updater_binary/update_processor_unittest.cpp index b0a2155c5cb676f46232fa0d6a75440f6ae7e84e..e86e72ee1f8975e2e64441d15331be331324a1ce 100755 --- a/test/unittest/updater_binary/update_processor_unittest.cpp +++ b/test/unittest/updater_binary/update_processor_unittest.cpp @@ -28,7 +28,8 @@ #include "updater/updater.h" #include "utils.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace uscript; using namespace std; using namespace hpackage; @@ -54,7 +55,7 @@ void UpdateProcessorUnitTest::SetUpTestCase(void) {} // do something at the each function end void UpdateProcessorUnitTest::TearDownTestCase(void) {} -TEST(UpdateProcessorUnitTest, UpdateProcessor_001) +HWTEST_F(UpdateProcessorUnitTest, UpdateProcessor_001, TestSize.Level1) { LoadSpecificFstab("/data/updater/applypatch/etc/fstab.ut.updater"); const string packagePath = "/data/updater/updater/raw_image_write.zip"; @@ -71,6 +72,11 @@ TEST(UpdateProcessorUnitTest, UpdateProcessor_001) updater::utils::MkdirRecursive(devDir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); int fd = open(devPath.c_str(), O_CREAT | O_WRONLY | O_EXCL, 0664); printf("@@@ devPath = %s, fd=%d\n", devPath.c_str(), fd); + if (fd < 0) { + printf("Open failed, fd = %d", fd); + FAIL(); + return; + } close(fd); for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) { diff --git a/test/unittest/updater_binary/updater_binary_unittest.cpp b/test/unittest/updater_binary/updater_binary_unittest.cpp index 1f0a3437c237f18e624eef0f16e9738baf019f8c..d6a48a4d46b264f8bd0cd1f311c114c953d8556d 100755 --- a/test/unittest/updater_binary/updater_binary_unittest.cpp +++ b/test/unittest/updater_binary/updater_binary_unittest.cpp @@ -32,6 +32,7 @@ using namespace std; using namespace hpackage; using namespace uscript; using namespace updater; +using namespace testing::ext; using namespace updater::utils; namespace { @@ -44,6 +45,13 @@ public: int32_t ret = CreatePackageBin(); EXPECT_EQ(0, ret); std::string path = TEST_PATH_TO + testPackageName; + int fd = open(GetTestCertName().c_str(), O_RDONLY); + if (fd < 0) { + cout << GetTestCertName() << " open failed, fd = " << fd << endl; + return -1; + } else { + close(fd); + } ret = ProcessUpdater(false, STDOUT_FILENO, path.c_str(), GetTestCertName().c_str()); ret = 0; return ret; @@ -121,6 +129,9 @@ protected: 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); } @@ -133,18 +144,23 @@ 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); free(comp[i].version); } - free(pkgInfo.productUpdateId); - free(pkgInfo.softwareVersion); - free(pkgInfo.date); - free(pkgInfo.time); + if (pkgInfo.productUpdateId != nullptr) { + free(pkgInfo.productUpdateId); + } + if (pkgInfo.softwareVersion != nullptr) { + free(pkgInfo.softwareVersion); + } + if (pkgInfo.date != nullptr) { + free(pkgInfo.date); + } + if (pkgInfo.time != nullptr) { + free(pkgInfo.time); + } free(comp); return ret; } @@ -183,7 +199,7 @@ private: } }; -TEST_F(UpdaterBinaryUnittest, TestUpdater) +HWTEST_F(UpdaterBinaryUnittest, TestUpdater, TestSize.Level1) { UpdaterBinaryUnittest test; EXPECT_EQ(0, test.TestUpdater()); diff --git a/test/unittest/updater_main_test/updater_main_unittest.cpp b/test/unittest/updater_main_test/updater_main_unittest.cpp index 80aecc240651cd0833e0265e51b26c3e16c48dcd..743278c81c2301b2c07af40679de5510c0cca127 100755 --- a/test/unittest/updater_main_test/updater_main_unittest.cpp +++ b/test/unittest/updater_main_test/updater_main_unittest.cpp @@ -24,9 +24,11 @@ #include "securec.h" #include "updater_main.h" #include "updater_ui.h" +#include "updater/updater.h" #include "utils.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace std; using namespace updater::utils; @@ -54,7 +56,7 @@ void UpdaterMainUnitTest::SetUpTestCase(void) if (MountForPath("/data") != 0) { cout << "MountForPath failed" << endl; } - PostUpdater(); + PostUpdater(true); } // end @@ -65,7 +67,7 @@ void UpdaterMainUnitTest::TearDownTestCase(void) unlink("/data/updater_stage.log"); } -TEST_F(UpdaterMainUnitTest, updater_main_test_001) +HWTEST_F(UpdaterMainUnitTest, updater_main_test_001, TestSize.Level1) { UpdateMessage boot {}; if (access("/data/updater/", 0)) { @@ -75,7 +77,8 @@ TEST_F(UpdaterMainUnitTest, updater_main_test_001) const std::string commandFile = "/data/updater/command"; auto fp = std::unique_ptr(fopen(commandFile.c_str(), "wb"), fclose); EXPECT_NE(fp, nullptr); - EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command), "boot_updater", sizeof(boot.command)), 0); + const std::string commandMsg = "boot_updater"; + EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command) - 1, commandMsg.c_str(), commandMsg.size()), 0); EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), "", sizeof(boot.update)), 0); bool bRet = WriteUpdaterMessage(commandFile, boot); EXPECT_EQ(bRet, true); @@ -86,25 +89,27 @@ TEST_F(UpdaterMainUnitTest, updater_main_test_001) std::vector args = ParseParams(argc, argv); EXPECT_EQ(args.size(), static_cast(argc)); - PostUpdater(); + PostUpdater(true); delete argv[0]; delete []argv; } -TEST_F(UpdaterMainUnitTest, updater_main_test_002) +HWTEST_F(UpdaterMainUnitTest, updater_main_test_002, TestSize.Level1) { UpdateMessage boot {}; - EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command), "boot_updater", sizeof(boot.command)), 0); - EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), "--user_wipe_data", sizeof(boot.update)), 0); + const std::string command1 = "boot_updater"; + EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command) - 1, command1.c_str(), command1.size()), 0); + const std::string command2 = "--user_wipe_data"; + EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update) - 1, command2.c_str(), command2.size()), 0); bool ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); int fRet = FactoryReset(USER_WIPE_DATA, "/misc/factory_test"); EXPECT_EQ(fRet, 0); - PostUpdater(); + PostUpdater(true); } -TEST_F(UpdaterMainUnitTest, updater_main_test_003) +HWTEST_F(UpdaterMainUnitTest, updater_main_test_003, TestSize.Level1) { const std::string sLog = "/data/updater/main_data/updater.tab"; const std::string dLog = "/data/updater/main_data/ut_dLog.txt"; @@ -113,16 +118,17 @@ TEST_F(UpdaterMainUnitTest, updater_main_test_003) unlink(dLog.c_str()); } -TEST_F(UpdaterMainUnitTest, updater_main_test_004) +HWTEST_F(UpdaterMainUnitTest, updater_main_test_004, TestSize.Level1) { UpdaterUiInit(); auto fp = std::unique_ptr(fopen("/data/updater/updater.zip", "wb"), fclose); EXPECT_NE(fp, nullptr); UpdateMessage boot {}; - EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command), "boot_updater", sizeof(boot.command)), 0); - EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), - "--update_package=/data/updater/updater.zip\n--retry_count=0", sizeof(boot.update)), 0); + const std::string command1 = "boot_updater"; + EXPECT_EQ(strncpy_s(boot.command, sizeof(boot.command) - 1, command1.c_str(), command1.size()), 0); + const std::string command2 = "--update_package=/data/updater/updater.zip\n--retry_count=0"; + EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update) - 1, command2.c_str(), command2.size()), 0); bool ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); @@ -132,16 +138,18 @@ TEST_F(UpdaterMainUnitTest, updater_main_test_004) int argc = 1; int lRet = UpdaterMain(argc, argv); EXPECT_EQ(lRet, 0); - + EXPECT_EQ(memset_s(boot.update, sizeof(boot.update), 0, sizeof(boot.update)), 0); - EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), "--user_wipe_data", sizeof(boot.update)), 0); + const std::string command3 = "--user_wipe_data"; + EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update) - 1, command3.c_str(), command3.size()), 0); ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); lRet = UpdaterMain(argc, argv); EXPECT_EQ(lRet, 0); EXPECT_EQ(memset_s(boot.update, sizeof(boot.update), 0, sizeof(boot.update)), 0); - EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update), "--factory_wipe_data", sizeof(boot.update)), 0); + const std::string command4 = "--factory_wipe_data"; + EXPECT_EQ(strncpy_s(boot.update, sizeof(boot.update) - 1, command4.c_str(), command4.size()), 0); ret = WriteUpdaterMessage(MISC_FILE, boot); EXPECT_EQ(ret, true); lRet = UpdaterMain(argc, argv); @@ -155,11 +163,11 @@ TEST_F(UpdaterMainUnitTest, updater_main_test_004) DeleteView(); } -TEST_F(UpdaterMainUnitTest, updater_main_test_compress) +HWTEST_F(UpdaterMainUnitTest, updater_main_test_compress, TestSize.Level1) { const std::string testFile = "/data/sdcard/updater/test_compress.txt"; FILE *fp = fopen(testFile.c_str(), "w"); - EXPECT_NE(fp, nullptr); + ASSERT_NE(fp, nullptr); fclose(fp); CompressLogs(testFile); } diff --git a/test/unittest/updater_test/updater_unittest.cpp b/test/unittest/updater_test/updater_unittest.cpp index 86c7915ce7389c999e1df69476b4217186b94a56..c11ffe0cb272c78d052847161ac8cba87f1a5e79 100755 --- a/test/unittest/updater_test/updater_unittest.cpp +++ b/test/unittest/updater_test/updater_unittest.cpp @@ -67,7 +67,7 @@ void UpdaterUnitTest::TearDownTestCase() DeleteView(); } -TEST_F(UpdaterUnitTest, updater_StartUpdaterProc) +HWTEST_F(UpdaterUnitTest, updater_StartUpdaterProc, TestSize.Level1) { std::string packagePath = "/data/updater/updater/updater_without_updater_binary.zip"; PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); @@ -97,7 +97,7 @@ TEST_F(UpdaterUnitTest, updater_StartUpdaterProc) EXPECT_EQ(status, UPDATE_ERROR); } -TEST_F(UpdaterUnitTest, updater_GetUpdatePackageInfo) +HWTEST_F(UpdaterUnitTest, updater_GetUpdatePackageInfo, TestSize.Level1) { // Non-exist file. PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); @@ -113,7 +113,7 @@ TEST_F(UpdaterUnitTest, updater_GetUpdatePackageInfo) EXPECT_EQ(ret, static_cast(PKG_SUCCESS)); } -TEST_F(UpdaterUnitTest, updater_UpdateSdcard) +HWTEST_F(UpdaterUnitTest, updater_UpdateSdcard, TestSize.Level1) { UpdaterStatus status; status = UpdaterFromSdcard(); diff --git a/test/unittest/updater_ui_test/updater_ui_unittest.cpp b/test/unittest/updater_ui_test/updater_ui_unittest.cpp index 22c4e71a6931096514bbd98e87239427cd7de5aa..19a4e04b46f05f55e96371c5e2be55d3c72b39ff 100755 --- a/test/unittest/updater_ui_test/updater_ui_unittest.cpp +++ b/test/unittest/updater_ui_test/updater_ui_unittest.cpp @@ -27,7 +27,8 @@ #include "utils.h" #include "input_event.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace std; using namespace updater::utils; static constexpr int EV_VALUE_15 = 15; @@ -61,7 +62,7 @@ void UpdaterUiUnitTest::TearDownTestCase(void) unlink("/data/updater_stage.log"); } -TEST_F(UpdaterUiUnitTest, updater_ui_test_HandleInputEvent) +HWTEST_F(UpdaterUiUnitTest, updater_ui_test_HandleInputEvent, TestSize.Level1) { UpdaterUiInit(); struct input_event ev {}; diff --git a/test/unittest/updaterkits_test/updaterkits_unittest.cpp b/test/unittest/updaterkits_test/updaterkits_unittest.cpp index d02d6e72a1e1076b48e71dbacf6c1414f8403f52..ec25205b2d3df831ea79397cd43705f9c46b882c 100755 --- a/test/unittest/updaterkits_test/updaterkits_unittest.cpp +++ b/test/unittest/updaterkits_test/updaterkits_unittest.cpp @@ -36,7 +36,7 @@ void UpdaterKitsUnitTest::TearDownTestCase(void) cout << "Updater Unit UpdaterKitsUnitTest End!" << endl; } -TEST_F(UpdaterKitsUnitTest, updater_kits_test01) +HWTEST_F(UpdaterKitsUnitTest, updater_kits_test01, TestSize.Level1) { const std::string packageName1 = ""; bool ret = RebootAndInstallUpgradePackage(MISC_FILE, packageName1); @@ -50,7 +50,7 @@ TEST_F(UpdaterKitsUnitTest, updater_kits_test01) unlink(MISC_FILE.c_str()); } -TEST_F(UpdaterKitsUnitTest, updater_kits_test02) +HWTEST_F(UpdaterKitsUnitTest, updater_kits_test02, TestSize.Level1) { const std::string cmd1 = ""; bool ret = RebootAndCleanUserData(MISC_FILE, cmd1); diff --git a/test/unittest/utils/utils_unittest.cpp b/test/unittest/utils/utils_unittest.cpp index a3b61cf1b1b991bc02ab206d4f77387bb8cee07a..eb40b025d89a7a108d35bf44fa2b070c0674ab3a 100755 --- a/test/unittest/utils/utils_unittest.cpp +++ b/test/unittest/utils/utils_unittest.cpp @@ -19,7 +19,8 @@ #include #include "utils.h" -using namespace updater; +using namespace updater; +using namespace testing::ext; using namespace std; namespace updater_ut { @@ -31,7 +32,7 @@ public: void TearDown() {}; }; -TEST_F(UtilsUnitTest, updater_utils_test_001) +HWTEST_F(UtilsUnitTest, updater_utils_test_001, TestSize.Level0) { string emptyStr = utils::Trim(""); EXPECT_STREQ(emptyStr.c_str(), ""); @@ -41,7 +42,7 @@ TEST_F(UtilsUnitTest, updater_utils_test_001) EXPECT_STREQ(emptyStr.c_str(), "aa"); } -TEST_F(UtilsUnitTest, updater_utils_test_002) +HWTEST_F(UtilsUnitTest, updater_utils_test_002, TestSize.Level0) { uint8_t a[1] = {0}; a[0] = 1; @@ -49,7 +50,7 @@ TEST_F(UtilsUnitTest, updater_utils_test_002) EXPECT_STREQ(newStr.c_str(), "01"); } -TEST_F(UtilsUnitTest, updater_utils_test_003) +HWTEST_F(UtilsUnitTest, updater_utils_test_003, TestSize.Level0) { string str = "aaa\nbbb"; vector newStr = utils::SplitString(str, "\n"); @@ -57,12 +58,12 @@ TEST_F(UtilsUnitTest, updater_utils_test_003) EXPECT_EQ(newStr[1], "bbb"); } -TEST_F(UtilsUnitTest, updater_utils_test_004) +HWTEST_F(UtilsUnitTest, updater_utils_test_004, TestSize.Level0) { EXPECT_EQ(utils::MkdirRecursive("/data/xx?xx", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), 0); } -TEST_F(UtilsUnitTest, updater_utils_test_005) +HWTEST_F(UtilsUnitTest, updater_utils_test_005, TestSize.Level0) { string input = ""; int output = utils::String2Int(input, 10); @@ -72,7 +73,7 @@ TEST_F(UtilsUnitTest, updater_utils_test_005) EXPECT_EQ(output, 1); } -TEST_F(UtilsUnitTest, updater_utils_test_006) +HWTEST_F(UtilsUnitTest, updater_utils_test_006, TestSize.Level0) { std::vector files; string path = "/data"; diff --git a/utils/BUILD.gn b/utils/BUILD.gn index 0702846199f126a0861100c73957ef8b76b34e3b..7a945c0c9fa2b216b0588e8a97cec7590d60addd 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -24,6 +24,10 @@ ohos_static_library("libutils") { ] deps = [ "//third_party/bounds_checking_function:libsec_static" ] + external_deps = [ "init:libbegetutil" ] + + subsystem_name = "updater" + part_name = "updater" } ohos_executable("updater_reboot") { @@ -62,6 +66,7 @@ ohos_executable("write_updater") { "//base/update/updater/utils:libutils", "//third_party/bounds_checking_function:libsec_static", ] + external_deps = [ "init:libbegetutil" ] install_enable = true part_name = "updater" diff --git a/utils/include/utils.h b/utils/include/utils.h index 9540675a322745eac639318f087077e5650284dc..62366084e62e2ca8e8aab82947224f6cd2a734a6 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -48,15 +48,13 @@ int64_t GetFilesFromDirectory(const std::string &path, std::vector std::vector SplitString(const std::string &str, const std::string del = " \t"); std::string Trim(const std::string &str); std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length); -void DoReboot(const std::string& rebootTarget); +void DoReboot(const std::string& rebootTarget, const std::string& extData = ""); std::string GetCertName(); bool WriteFully(int fd, const void *data, size_t size); bool ReadFully(int fd, void* data, size_t size); bool ReadFileToString(int fd, std::string &content); bool WriteStringToFile(int fd, const std::string& content); std::string GetLocalBoardId(); -bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog); -void CompressLogs(const std::string &name); } // utils } // updater #endif // UPDATER_UTILS_H diff --git a/utils/updater_reboot.cpp b/utils/updater_reboot.cpp index 87546f3b95ec088807c8648b24372a4873d31ef4..42e189f8a26d7d99922fd562d77919647d2f9c80 100644 --- a/utils/updater_reboot.cpp +++ b/utils/updater_reboot.cpp @@ -32,8 +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], "flashd") == 0) { + updater::utils::DoReboot(argv[1]); + } 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!"; + updater::LOG(updater::INFO) << "param must be updater/flashd!"; } } return 0; diff --git a/utils/utils.cpp b/utils/utils.cpp index 52c0b2015f971e7c1caa4df6375428e1d58f4caf..3da6a9a1b0d257080c8287bf23a6639085b1ece1 100644 --- a/utils/utils.cpp +++ b/utils/utils.cpp @@ -39,8 +39,6 @@ using namespace hpackage; namespace utils { constexpr uint32_t MAX_PATH_LEN = 256; constexpr uint8_t SHIFT_RIGHT_FOUR_BITS = 4; -constexpr int USER_ROOT_AUTHORITY = 0; -constexpr int GROUP_SYS_AUTHORITY = 1000; int32_t DeleteFile(const std::string& filename) { UPDATER_ERROR_CHECK (!filename.empty(), "Invalid filename", return -1); @@ -159,32 +157,44 @@ std::string ConvertSha256Hex(const uint8_t* shaDigest, size_t length) return haxSha256; } -void DoReboot(const std::string& rebootTarget) +void DoReboot(const std::string& rebootTarget, const std::string &extData) { LOG(INFO) << ", rebootTarget: " << rebootTarget; static const int32_t maxCommandSize = 16; LoadFstab(); auto miscBlockDevice = GetBlockDeviceByMountPoint("/misc"); struct UpdateMessage msg; - if (rebootTarget == "updater") { + if (rebootTarget.empty()) { + UPDATER_ERROR_CHECK(!memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE), "Memset_s failed", return); + if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { + LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error"; + return; + } + sync(); + } else { + int result = 0; bool ret = ReadUpdaterMessage(miscBlockDevice, msg); UPDATER_ERROR_CHECK(ret == true, "DoReboot read misc failed", return); - if (strcmp(msg.command, "boot_updater") != 0) { - UPDATER_ERROR_CHECK(!memcpy_s(msg.command, maxCommandSize, "boot_updater", maxCommandSize - 1), - "Memcpy failed", return); + if (rebootTarget == "updater" && strcmp(msg.command, "boot_updater") != 0) { + result = strcpy_s(msg.command, maxCommandSize, "boot_updater"); + msg.command[maxCommandSize] = 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) { + result = strcpy_s(msg.command, maxCommandSize, "boot_loader"); msg.command[maxCommandSize] = 0; } - ret = WriteUpdaterMessage(miscBlockDevice, msg); - if (ret != true) { - LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; - return; + UPDATER_ERROR_CHECK(result == 0, "strcpy failed", return); + if (!extData.empty()) { + 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); } - sync(); - } else { - UPDATER_ERROR_CHECK(!memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE), "Memset_s failed", return); - bool ret = WriteUpdaterMessage(miscBlockDevice, msg); - if (ret != true) { - LOG(INFO) << "DoReboot: WriteUpdaterMessage empty error"; + if (WriteUpdaterMessage(miscBlockDevice, msg) != true) { + LOG(INFO) << "DoReboot: WriteUpdaterMessage boot_updater error"; return; } sync(); @@ -277,74 +287,5 @@ std::string GetLocalBoardId() { return "HI3516"; } - -void CompressLogs(const std::string &name) -{ - PkgManager::PkgManagerPtr pkgManager = PkgManager::GetPackageInstance(); - UPDATER_ERROR_CHECK(pkgManager != nullptr, "pkgManager is nullptr", return); - std::vector> files; - // Build the zip file to be packaged - std::vector testFileNames; - std::string realName = name.substr(name.find_last_of("/") + 1); - testFileNames.push_back(realName); - for (auto name : testFileNames) { - ZipFileInfo file; - file.fileInfo.identity = name; - file.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP; - file.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; - std::string fileName = "/data/updater/log/" + name; - files.push_back(std::pair(fileName, file)); - } - - PkgInfo pkgInfo; - pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; - pkgInfo.digestMethod = PKG_DIGEST_TYPE_SHA256; - pkgInfo.pkgType = PKG_PACK_TYPE_ZIP; - - char realTime[MAX_TIME_SIZE] = {0}; - auto sysTime = std::chrono::system_clock::now(); - auto currentTime = std::chrono::system_clock::to_time_t(sysTime); - struct tm *localTime = std::localtime(¤tTime); - if (localTime != nullptr) { - std::strftime(realTime, sizeof(realTime), "%H_%M_%S", localTime); - } - char pkgName[MAX_LOG_NAME_SIZE]; - UPDATER_CHECK_ONLY_RETURN(snprintf_s(pkgName, MAX_LOG_NAME_SIZE, MAX_LOG_NAME_SIZE - 1, - "/data/updater/log/%s_%s.zip", realName.c_str(), realTime) != -1, return); - int32_t ret = pkgManager->CreatePackage(pkgName, GetCertName(), &pkgInfo, files); - UPDATER_CHECK_ONLY_RETURN(ret != 0, return); - UPDATER_CHECK_ONLY_RETURN(DeleteFile(name) == 0, return); -} - -bool CopyUpdaterLogs(const std::string &sLog, const std::string &dLog) -{ - UPDATER_WARING_CHECK(MountForPath(UPDATER_LOG_DIR) == 0, "MountForPath /data/log failed!", return false); - if (access(UPDATER_LOG_DIR.c_str(), 0) != 0) { - UPDATER_ERROR_CHECK(!MkdirRecursive(UPDATER_LOG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH), - "MkdirRecursive error!", return false); - UPDATER_ERROR_CHECK(chown(UPDATER_PATH.c_str(), USER_ROOT_AUTHORITY, GROUP_SYS_AUTHORITY) == 0, - "Chown failed!", return false); - UPDATER_ERROR_CHECK(chmod(UPDATER_PATH.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0, - "Chmod failed!", return false); - } - - FILE* dFp = fopen(dLog.c_str(), "ab+"); - UPDATER_ERROR_CHECK(dFp != nullptr, "open log failed", return false); - - FILE* sFp = fopen(sLog.c_str(), "r"); - UPDATER_ERROR_CHECK(sFp != nullptr, "open log failed", fclose(dFp); return false); - - char buf[MAX_LOG_BUF_SIZE]; - size_t bytes; - while ((bytes = fread(buf, 1, sizeof(buf), sFp)) != 0) { - fwrite(buf, 1, bytes, dFp); - } - fseek(dFp, 0, SEEK_END); - UPDATER_INFO_CHECK(ftell(dFp) < MAX_LOG_SIZE, "log size greater than 5M!", CompressLogs(dLog)); - sync(); - fclose(sFp); - fclose(dFp); - return true; -} } // utils } // namespace updater