diff --git a/services/applypatch/command_process.cpp b/services/applypatch/command_process.cpp index ab5e82ff85a0e7f24cd0140e8c183afcd713cab2..dba56dfb263ef573976010eee12ba0d2e159394a 100644 --- a/services/applypatch/command_process.cpp +++ b/services/applypatch/command_process.cpp @@ -196,6 +196,26 @@ int32_t DiffAndMoveCommandFn::WriteDiffToBlock(const Command ¶ms, std::vecto return targetBlock.WriteDiffToBlock(params, srcBuffer, patchBuffer, patchLength, type == CommandType::IMGDIFF); } +int32_t DiffAndMoveCommandFn::WriteFileToBlock(const Command ¶ms, std::vector &srcBuffer, + size_t offset, size_t patchLength, BlockSet &targetBlock) +{ + std::ifstream fin(params.GetTransferParams()->patchDatFile, std::ios::in | std::ios::binary); + if (!fin.is_open()) { + LOG(ERROR) << "open dat file failed " << params.GetTransferParams()->patchDatFile; + return static_cast(FAILED); + } + std::unique_ptr patchBuffer = std::make_unique(patchLength); + (void)memset_s(patchBuffer.get(), patchLength, 0, patchLength); + if ((!fin.seekg(static_cast(offset), std::ios::beg)) || + (!fin.read(reinterpret_cast(patchBuffer.get()), patchLength))) { + LOG(ERROR) << "read dat file failed gcount " << fin.gcount() << ", patch len " << patchLength; + fin.close(); + return static_cast(FAILED); + } + fin.close(); + return WriteDiffToBlock(params, srcBuffer, patchBuffer.get(), patchLength, targetBlock); +} + CommandResult DiffAndMoveCommandFn::Execute(const Command ¶ms) { CommandType type = params.GetCommandType(); @@ -227,8 +247,12 @@ CommandResult DiffAndMoveCommandFn::Execute(const Command ¶ms) offset = Utils::String2Int(params.GetArgumentByPos(pos++), Utils::N_DEC); } size_t patchLength = Utils::String2Int(params.GetArgumentByPos(pos++), Utils::N_DEC); - uint8_t *patchBuffer = params.GetTransferParams()->dataBuffer + offset; - ret = WriteDiffToBlock(params, buffer, patchBuffer, patchLength, targetBlock); + if (params.GetTransferParams()->isUpdaterMode) { + uint8_t *patchBuffer = params.GetTransferParams()->dataBuffer + offset; + ret = WriteDiffToBlock(params, buffer, patchBuffer, patchLength, targetBlock); + } else { + ret = WriteFileToBlock(params, buffer, offset, patchLength, targetBlock); + } } else { ret = targetBlock.WriteDataToBlock(params.GetTargetFileDescriptor(), buffer) == 0 ? -1 : 0; } diff --git a/services/applypatch/command_process.h b/services/applypatch/command_process.h index 42f554b9edb07c4beb44976c599369e119c75df5..48caa869bd619a089166ede447fb6941e905d538 100644 --- a/services/applypatch/command_process.h +++ b/services/applypatch/command_process.h @@ -63,6 +63,8 @@ public: CommandResult Execute(const Command ¶ms) override; virtual int32_t WriteDiffToBlock(const Command ¶ms, std::vector &srcBuffer, uint8_t *patchBuffer, size_t patchLength, BlockSet &targetBlock); + virtual int32_t WriteFileToBlock(const Command ¶ms, std::vector &srcBuffer, + size_t offset, size_t patchLength, BlockSet &targetBlock); }; } #endif // UPDATER_COMMAND_PROCESS_H diff --git a/services/include/applypatch/transfer_manager.h b/services/include/applypatch/transfer_manager.h index d67bf800c213ad3437baae11a4a31421d85492ae..0cb771274cc3fd94e2262b1b3d4432be0d5b45a6 100644 --- a/services/include/applypatch/transfer_manager.h +++ b/services/include/applypatch/transfer_manager.h @@ -52,9 +52,11 @@ struct TransferParams { std::string freeStash; std::string retryFile; std::string devPath; + std::string patchDatFile; uint8_t *dataBuffer; size_t dataBufferSize; bool canWrite; + bool isUpdaterMode; }; class TransferManager; diff --git a/services/package/pkg_algorithm/pkg_algo_deflate.cpp b/services/package/pkg_algorithm/pkg_algo_deflate.cpp index d0763552c12b42a6ea89e682c46221cd2568869b..96be701b1376a4375df964ed2804241c743c50f9 100644 --- a/services/package/pkg_algorithm/pkg_algo_deflate.cpp +++ b/services/package/pkg_algorithm/pkg_algo_deflate.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "pkg_algo_deflate.h" +#include #include "pkg_stream.h" #include "pkg_utils.h" #include "securec.h" @@ -23,6 +24,7 @@ constexpr uint32_t DEFLATE_IN_BUFFER_SIZE = 1024 * 64; constexpr uint32_t DEFLATE_OUT_BUFFER_SIZE = 1024 * 32; constexpr uint32_t INFLATE_IN_BUFFER_SIZE = 1024 * 1024 * 1024; constexpr uint32_t INFLATE_OUT_BUFFER_SIZE = 1024 * 1024; +constexpr uint32_t INFLATE_IN_BUFFER_SIZE_NORMAL_MODE = 10 * 1024 * 1024; int32_t PkgAlgoDeflate::DeflateData(const PkgStreamPtr outStream, z_stream &zstream, int32_t flush, PkgBuffer &outBuffer, size_t &destOffset) const @@ -235,7 +237,8 @@ int32_t PkgAlgoDeflate::InitStream(z_stream &zstream, bool zip, PkgBuffer &inBuf PKG_LOGE("fail deflateInit2"); return PKG_NOT_EXIST_ALGORITHM; } - inBuffer.length = INFLATE_IN_BUFFER_SIZE; + inBuffer.length = (access("/bin/updater", 0) == 0) ? + INFLATE_IN_BUFFER_SIZE : INFLATE_IN_BUFFER_SIZE_NORMAL_MODE; outBuffer.length = INFLATE_OUT_BUFFER_SIZE; } diff --git a/services/package/pkg_manager/pkg_managerImpl.cpp b/services/package/pkg_manager/pkg_managerImpl.cpp index b19710b1af46c6054cd060872e8ec389d870d2ce..e2d0d39498d2a010cf5600330daf47c6e434f0b0 100644 --- a/services/package/pkg_manager/pkg_managerImpl.cpp +++ b/services/package/pkg_manager/pkg_managerImpl.cpp @@ -384,7 +384,10 @@ int32_t PkgManagerImpl::LoadPackage(const std::string &packagePath, std::vector< { UPDATER_INIT_RECORD; PkgStreamPtr stream = nullptr; - int32_t ret = CreatePkgStream(stream, packagePath, 0, PkgStream::PKgStreamType_FileMap); + // using PkgStreamType_Read type to reduce memory usage + auto streamType = (access("/bin/updater", 0) == 0) ? + PkgStream::PKgStreamType_FileMap : PkgStream::PkgStreamType_Read; + int32_t ret = CreatePkgStream(stream, packagePath, 0, streamType); if (ret != PKG_SUCCESS) { PKG_LOGE("Create input stream fail %s", packagePath.c_str()); UPDATER_LAST_WORD(ret, "CreatePkgStream failed"); diff --git a/services/package/pkg_manager/pkg_stream.cpp b/services/package/pkg_manager/pkg_stream.cpp index 602821eac7ad074cd5abca5cc61123b675b8ec02..48a4150ec1e6c77a2e02d5160607d56b750f4197 100644 --- a/services/package/pkg_manager/pkg_stream.cpp +++ b/services/package/pkg_manager/pkg_stream.cpp @@ -75,6 +75,7 @@ FileStream::~FileStream() int32_t FileStream::Read(PkgBuffer &data, size_t start, size_t needRead, size_t &readLen) { Updater::UPDATER_INIT_RECORD; + std::lock_guard lock(fileStreamLock_); if (stream_ == nullptr) { PKG_LOGE("Invalid stream"); UPDATER_LAST_WORD(PKG_INVALID_STREAM, "Invalid stream"); @@ -111,6 +112,7 @@ int32_t FileStream::Read(PkgBuffer &data, size_t start, size_t needRead, size_t int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t start) { + std::lock_guard lock(fileStreamLock_); if (streamType_ != PkgStreamType_Write) { PKG_LOGE("Invalid stream type"); return PKG_INVALID_STREAM; @@ -134,6 +136,7 @@ int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t start) size_t FileStream::GetFileLength() { + std::lock_guard lock(fileStreamLock_); if (stream_ == nullptr) { PKG_LOGE("Invalid stream"); return 0; @@ -159,6 +162,7 @@ size_t FileStream::GetFileLength() int32_t FileStream::Seek(long int offset, int whence) { + std::lock_guard lock(fileStreamLock_); if (stream_ == nullptr) { PKG_LOGE("Invalid stream"); return PKG_INVALID_STREAM; @@ -168,6 +172,7 @@ int32_t FileStream::Seek(long int offset, int whence) int32_t FileStream::Flush(size_t size) { + std::lock_guard lock(fileStreamLock_); if (stream_ == nullptr) { PKG_LOGE("Invalid stream"); return PKG_INVALID_STREAM; diff --git a/services/package/pkg_manager/pkg_stream.h b/services/package/pkg_manager/pkg_stream.h index 5b8e6166334f482522395f4f622b31c5bbc5eb7c..62ce18a0d5a8000468222e9edae385132b27470e 100644 --- a/services/package/pkg_manager/pkg_stream.h +++ b/services/package/pkg_manager/pkg_stream.h @@ -112,6 +112,7 @@ private: FILE *stream_; size_t fileLength_; int32_t streamType_; + std::recursive_mutex fileStreamLock_; }; class MemoryMapStream : public PkgStreamImpl { diff --git a/services/updater_binary/update_image_block.cpp b/services/updater_binary/update_image_block.cpp index 9e1c49fcf6ed996500c8f5c61e1d18b25e5fa318..95a6048fcd6fb514d8a814864602d64516987ab0 100644 --- a/services/updater_binary/update_image_block.cpp +++ b/services/updater_binary/update_image_block.cpp @@ -345,6 +345,34 @@ static int32_t ExtractFileByName(Uscript::UScriptEnv &env, const std::string &fi return USCRIPT_SUCCESS; } +static int32_t ExtractPatchDatFile(Uscript::UScriptEnv &env, const UpdateBlockInfo &infos, + Hpackage::PkgManager::StreamPtr &outStream, std::string &datFile) +{ + if (env.GetPkgManager() == nullptr) { + LOG(ERROR) << "Error to get pkg manager"; + return USCRIPT_ERROR_EXECUTE; + } + + if ((!Utils::IsDirExist(UPDATER_PATH)) && (Utils::MkdirRecursive(UPDATER_PATH, S_IRWXU) != 0)) { + LOG(ERROR) << "Failed to make path"; + return USCRIPT_ERROR_EXECUTE; + } + std::string fileName = std::string(UPDATER_PATH) + "/" + infos.patchDataName; + auto ret = env.GetPkgManager()->CreatePkgStream(outStream, fileName, 0, PkgStream::PkgStreamType_Write); + if (ret != USCRIPT_SUCCESS || outStream == nullptr) { + LOG(ERROR) << "Error to create output stream"; + return USCRIPT_ERROR_EXECUTE; + } + ret = env.GetPkgManager()->ExtractFile(infos.patchDataName, outStream); + if (ret != USCRIPT_SUCCESS) { + LOG(ERROR) << "Error to extract file"; + env.GetPkgManager()->ClosePkgStream(outStream); + return USCRIPT_ERROR_EXECUTE; + } + datFile = fileName; + return USCRIPT_SUCCESS; +} + static int32_t ExecuteUpdateBlock(Uscript::UScriptEnv &env, Uscript::UScriptContext &context) { UpdateBlockInfo infos {}; @@ -385,8 +413,11 @@ static int32_t ExecuteUpdateBlock(Uscript::UScriptEnv &env, Uscript::UScriptCont env.GetPkgManager()->ClosePkgStream(outStream); LOG(INFO) << "Start unpack new data thread done. Get patch data: " << infos.patchDataName; - if (ExtractFileByName(env, infos.patchDataName, outStream, - transferParams->dataBuffer, transferParams->dataBufferSize) != USCRIPT_SUCCESS) { + transferParams->isUpdaterMode = Utils::IsUpdaterMode(); + int ret = transferParams->isUpdaterMode ? ExtractFileByName(env, infos.patchDataName, outStream, + transferParams->dataBuffer, transferParams->dataBufferSize) : ExtractPatchDatFile(env, + infos, outStream, transferParams->patchDatFile); + if (ret != USCRIPT_SUCCESS) { return USCRIPT_ERROR_EXECUTE; }