• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "update_processor.h"
16 #include <cstdio>
17 #include <memory>
18 #include <string>
19 #include <unistd.h>
20 #include <pthread.h>
21 #include "securec.h"
22 #include "applypatch/data_writer.h"
23 #include "applypatch/partition_record.h"
24 #include "applypatch/update_progress.h"
25 #include "dump.h"
26 #include "log.h"
27 #include "package/hash_data_verifier.h"
28 #include "pkg_manager.h"
29 #ifdef UPDATER_USE_PTABLE
30 #include "ptable_manager.h"
31 #endif
32 #include "script_instruction.h"
33 #include "script_manager.h"
34 #include "slot_info/slot_info.h"
35 #include "update_image_block.h"
36 #include "update_image_patch.h"
37 #include "update_partitions.h"
38 #include "updater_main.h"
39 #include "updater/updater_const.h"
40 #include "update_bin/bin_process.h"
41 #include "scope_guard.h"
42 
43 using namespace Uscript;
44 using namespace Hpackage;
45 using namespace Updater;
46 
47 namespace Updater {
48 size_t UScriptInstructionRawImageWrite::totalSize_ = 0;
49 size_t UScriptInstructionRawImageWrite::readSize_ = 0;
50 size_t UScriptInstructionUpdateFromBin::stashDataSize_ = 0;
51 
GetFinalBinaryResult(int32_t result)52 __attribute__((weak)) int32_t GetFinalBinaryResult(int32_t result)
53 {
54     return result;
55 }
56 
~UpdaterEnv()57 UpdaterEnv::~UpdaterEnv()
58 {
59     if (factory_ != nullptr) {
60         delete factory_;
61         factory_ = nullptr;
62     }
63 }
64 
PostMessage(const std::string & cmd,std::string content)65 void UpdaterEnv::PostMessage(const std::string &cmd, std::string content)
66 {
67     if (postMessage_ != nullptr) {
68         std::lock_guard<std::mutex> lock(messageLock_);
69         postMessage_(cmd.c_str(), content.c_str());
70     }
71 }
72 
GetInstructionFactory()73 UScriptInstructionFactoryPtr UpdaterEnv::GetInstructionFactory()
74 {
75     if (factory_ == nullptr) {
76         factory_ = new UpdaterInstructionFactory();
77     }
78     return factory_;
79 }
80 
GetInstructionNames() const81 const std::vector<std::string> UpdaterEnv::GetInstructionNames() const
82 {
83     static std::vector<std::string> updaterCmds = {
84         "sha_check", "first_block_check", "block_update",
85         "raw_image_write", "update_partitions", "image_patch",
86         "image_sha_check", "pkg_extract", "pkg_extract_no_ret", "update_from_bin"
87     };
88     return updaterCmds;
89 }
90 
CreateInstructionInstance(UScriptInstructionPtr & instr,const std::string & name)91 int32_t UpdaterInstructionFactory::CreateInstructionInstance(UScriptInstructionPtr& instr,
92     const std::string& name)
93 {
94     if (name == "sha_check") {
95         instr = new UScriptInstructionShaCheck();
96     } else if (name == "first_block_check") {
97         instr = new UScriptInstructionBlockCheck();
98     } else if (name == "block_update") {
99         instr = new UScriptInstructionBlockUpdate();
100     } else if (name == "raw_image_write") {
101         instr = new UScriptInstructionRawImageWrite();
102     } else if (name == "update_partitions") {
103         instr = new UpdatePartitions();
104     } else if (name == "image_patch") {
105         instr = new USInstrImagePatch();
106     } else if (name == "image_sha_check") {
107         instr = new USInstrImageShaCheck();
108     } else if (name == "pkg_extract") {
109         instr = new UScriptInstructionPkgExtract();
110     } else if (name == "pkg_extract_no_ret") {
111         instr = new UScriptInstructionPkgExtractRetSuc();
112     } else if (name == "update_from_bin") {
113         instr = new UScriptInstructionBinFlowWrite();
114     }
115     return USCRIPT_SUCCESS;
116 }
117 
RawImageWriteProcessor(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)118 int UScriptInstructionRawImageWrite::RawImageWriteProcessor(const PkgBuffer &buffer, size_t size, size_t start,
119                                                             bool isFinish, const void* context)
120 {
121     void *p = const_cast<void *>(context);
122     DataWriter *writer = static_cast<DataWriter *>(p);
123     if (writer == nullptr) {
124         LOG(ERROR) << "Data writer is null";
125         return PKG_INVALID_STREAM;
126     }
127 
128     // maybe extract from package is finished. just return.
129     if (buffer.buffer == nullptr || size == 0) {
130         return PKG_SUCCESS;
131     }
132 
133     bool ret = writer->Write(const_cast<uint8_t*>(buffer.buffer), size, nullptr);
134     if (!ret) {
135         LOG(ERROR) << "Write " << size << " byte(s) failed";
136         return PKG_INVALID_STREAM;
137     }
138 
139     if (totalSize_ != 0) {
140         readSize_ += size;
141         writer->GetUpdaterEnv()->PostMessage("set_progress", std::to_string((float)readSize_ / totalSize_));
142     }
143 
144     return PKG_SUCCESS;
145 }
146 
WriteRawImage(const std::string & partitionName,const std::unique_ptr<DataWriter> & writer,uint64_t partitionSize,Uscript::UScriptEnv & env)147 bool UScriptInstructionRawImageWrite::WriteRawImage(const std::string &partitionName,
148     const std::unique_ptr<DataWriter> &writer, [[maybe_unused]] uint64_t partitionSize, Uscript::UScriptEnv &env)
149 {
150     UPDATER_INIT_RECORD;
151     // Extract partition information
152     const FileInfo *info = env.GetPkgManager()->GetFileInfo(partitionName);
153     if (info == nullptr) {
154         LOG(ERROR) << "Error to get file info";
155         UPDATER_LAST_WORD("Error to get file info", partitionName);
156         return false;
157     }
158     totalSize_ = info->unpackedSize;
159 #ifdef UPDATER_USE_PTABLE
160     if (partitionSize < totalSize_) {
161         LOG(ERROR) << "partition size: " << partitionSize << " is short than image size: " << totalSize_;
162         UPDATER_LAST_WORD(false);
163         return false;
164     }
165 #endif
166 
167     Hpackage::PkgManager::StreamPtr outStream = nullptr;
168     int ret = env.GetPkgManager()->CreatePkgStream(outStream,
169         partitionName, RawImageWriteProcessor, writer.get());
170     if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
171         LOG(ERROR) << "Error to create output stream";
172         UPDATER_LAST_WORD("Error to create output stream", partitionName);
173         return false;
174     }
175 
176     ret = env.GetPkgManager()->ExtractFile(partitionName, outStream);
177     if (ret != USCRIPT_SUCCESS) {
178         LOG(ERROR) << "Error to extract file";
179         env.GetPkgManager()->ClosePkgStream(outStream);
180         UPDATER_LAST_WORD("Error to extract file", partitionName);
181         return false;
182     }
183     env.GetPkgManager()->ClosePkgStream(outStream);
184     return true;
185 }
186 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)187 int32_t UScriptInstructionRawImageWrite::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
188 {
189     UPDATER_INIT_RECORD;
190     std::string partitionName;
191     int32_t ret = context.GetParam(0, partitionName);
192     if (ret != USCRIPT_SUCCESS) {
193         LOG(ERROR) << "Error to get partitionName";
194         UPDATER_LAST_WORD(ret, "Error to get partitionName");
195         return ret;
196     }
197 
198     if (env.IsRetry()) {
199         LOG(DEBUG) << "Retry updater, check if current partition updated already during last time";
200         if (PartitionRecord::GetInstance().IsPartitionUpdated(partitionName)) {
201             LOG(INFO) << partitionName << " already updated, skip";
202             return USCRIPT_SUCCESS;
203         }
204     }
205     LOG(INFO) << "UScriptInstructionRawImageWrite::Execute " << partitionName;
206     if (env.GetPkgManager() == nullptr) {
207         LOG(ERROR) << "Error to get pkg manager";
208         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "UScriptInstructionRawImageWrite::Execute " + partitionName);
209         return USCRIPT_ERROR_EXECUTE;
210     }
211 
212     std::string writePath;
213     uint64_t offset = 0;
214     uint64_t partitionSize = 0;
215     if (GetWritePathAndOffset(partitionName, writePath, offset, partitionSize) != USCRIPT_SUCCESS) {
216         LOG(ERROR) << "Get partition:%s WritePathAndOffset fail \'" <<
217             partitionName.substr(1, partitionName.size()) << "\'.";
218         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "GetWritePathAndOffset fail " + partitionName);
219         return USCRIPT_ERROR_EXECUTE;
220     }
221 
222     std::unique_ptr<DataWriter> writer = DataWriter::CreateDataWriter(WRITE_RAW, writePath,
223         static_cast<UpdaterEnv *>(&env), offset);
224     if (writer == nullptr) {
225         LOG(ERROR) << "Error to create writer";
226         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "Error to create writer");
227         return USCRIPT_ERROR_EXECUTE;
228     }
229     if (!WriteRawImage(partitionName, writer, partitionSize, env)) {
230         DataWriter::ReleaseDataWriter(writer);
231         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "WriteRawImage failed");
232         return USCRIPT_ERROR_EXECUTE;
233     }
234     PartitionRecord::GetInstance().RecordPartitionUpdateStatus(partitionName, true);
235     DataWriter::ReleaseDataWriter(writer);
236     totalSize_ = 0;
237     readSize_ = 0;
238     LOG(INFO) << "UScriptInstructionRawImageWrite finish";
239     return USCRIPT_SUCCESS;
240 }
241 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)242 int32_t UScriptInstructionPkgExtract::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
243 {
244     UPDATER_INIT_RECORD;
245     std::string pkgFileName;
246     int32_t ret = context.GetParam(0, pkgFileName);
247     if (ret != USCRIPT_SUCCESS) {
248         LOG(ERROR) << "Error to get pkgFileName";
249         UPDATER_LAST_WORD(ret, "Error to get pkgFileName");
250         return ret;
251     }
252 
253     std::string destPath;
254     ret = context.GetParam(1, destPath);
255     if (ret != USCRIPT_SUCCESS) {
256         LOG(ERROR) << "Error to get destPath";
257         UPDATER_LAST_WORD(ret, "Error to get destPath");
258         return ret;
259     }
260 
261     LOG(INFO) << "UScriptInstructionPkgExtract::Execute " << pkgFileName;
262     PkgManager::PkgManagerPtr manager = env.GetPkgManager();
263     if (manager == nullptr) {
264         LOG(ERROR) << "Error to get pkg manager";
265         UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM, "Error to get pkg manager");
266         return USCRIPT_INVALID_PARAM;
267     }
268 
269     const FileInfo *info = manager->GetFileInfo(pkgFileName);
270     if (info == nullptr) {
271         LOG(ERROR) << "Error to get file info";
272         UPDATER_LAST_WORD("Error to get file info", pkgFileName);
273         return USCRIPT_INVALID_PARAM;
274     }
275 
276     Hpackage::PkgManager::StreamPtr outStream = nullptr;
277     ret = manager->CreatePkgStream(outStream, destPath + "/" + pkgFileName, info->unpackedSize,
278         PkgStream::PkgStreamType_Write);
279     if (ret != USCRIPT_SUCCESS) {
280         LOG(ERROR) << "Error to create output stream";
281         UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM, "Error to create output stream");
282         return USCRIPT_ERROR_EXECUTE;
283     }
284 
285     ret = manager->ExtractFile(pkgFileName, outStream);
286     if (ret != USCRIPT_SUCCESS) {
287         LOG(ERROR) << "Error to extract file";
288         manager->ClosePkgStream(outStream);
289         UPDATER_LAST_WORD("Error to create output stream", pkgFileName);
290         return USCRIPT_ERROR_EXECUTE;
291     }
292 
293     manager->ClosePkgStream(outStream);
294     LOG(INFO)<<"UScriptInstructionPkgExtract finish";
295     return ret;
296 }
297 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)298 int32_t UScriptInstructionPkgExtractRetSuc::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
299 {
300     std::unique_lock<std::mutex> lock(extractNoRetMutex_);
301     int32_t ret = UScriptInstructionPkgExtract::Execute(env, context);
302     if (ret != USCRIPT_SUCCESS) {
303         LOG(ERROR) << "Error to extract file, ret = " << ret;
304     }
305     return USCRIPT_SUCCESS;
306 }
307 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)308 int32_t UScriptInstructionUpdateFromBin::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
309 {
310     std::string upgradeFileName;
311     int32_t ret = context.GetParam(0, upgradeFileName);
312     if (ret != USCRIPT_SUCCESS) {
313         LOG(ERROR) << "Error to get partitionName";
314         return ret;
315     }
316 
317     LOG(INFO) << "UScriptInstructionUpdateFromBin::Execute " << upgradeFileName;
318 
319     PkgManager::PkgManagerPtr pkgManager = env.GetPkgManager();
320     if (pkgManager == nullptr) {
321         LOG(ERROR) << "Error to get pkg manager";
322         return USCRIPT_INVALID_PARAM;
323     }
324 
325     RingBuffer ringBuffer;
326     if (!ringBuffer.Init(STASH_BUFFER_SIZE, BUFFER_NUM)) {
327         LOG(ERROR) << "Error to get ringbuffer";
328         return USCRIPT_INVALID_PARAM;
329     }
330 
331     PkgManager::StreamPtr outStream = nullptr;
332     ret = pkgManager->CreatePkgStream(outStream, upgradeFileName, UnCompressDataProducer, &ringBuffer);
333     if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
334         LOG(ERROR) << "Error to create output stream";
335         return USCRIPT_INVALID_PARAM;
336     }
337 
338     ret = pkgManager->ExtractFile(upgradeFileName, outStream);
339     if (ret != USCRIPT_SUCCESS) {
340         LOG(ERROR) << "Error to extract" << upgradeFileName;
341         pkgManager->ClosePkgStream(outStream);
342         return USCRIPT_ERROR_EXECUTE;
343     }
344     pkgManager->ClosePkgStream(outStream);
345     return USCRIPT_ERROR_EXECUTE;
346 }
347 
UnCompressDataProducer(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)348 int UScriptInstructionUpdateFromBin::UnCompressDataProducer(const PkgBuffer &buffer, size_t size, size_t start,
349                                                             bool isFinish, const void* context)
350 {
351     static PkgBuffer stashBuffer(STASH_BUFFER_SIZE);
352     size_t bufferStart = 0;
353     void *p = const_cast<void *>(context);
354     RingBuffer *ringBuffer = static_cast<RingBuffer *>(p);
355     if (ringBuffer == nullptr) {
356         LOG(ERROR) << "ring buffer is nullptr";
357         return PKG_INVALID_STREAM;
358     }
359 
360     while (stashDataSize_ + size >= STASH_BUFFER_SIZE) {
361         size_t readLen = STASH_BUFFER_SIZE - stashDataSize_;
362         if (memcpy_s(stashBuffer.buffer + stashDataSize_, readLen, buffer.buffer + bufferStart, readLen) != 0) {
363                 return USCRIPT_ERROR_EXECUTE;
364         }
365         ringBuffer->Push(stashBuffer.buffer, STASH_BUFFER_SIZE);
366         stashDataSize_ = 0;
367         size -= readLen;
368         bufferStart += readLen;
369     }
370     if (size == 0 && stashDataSize_ == 0) {
371         return PKG_SUCCESS;
372     } else if (size == 0 || memcpy_s(stashBuffer.buffer + stashDataSize_, STASH_BUFFER_SIZE - stashDataSize_,
373         buffer.buffer + bufferStart, size) == 0) {
374         if (isFinish) {
375             ringBuffer->Push(stashBuffer.buffer, stashDataSize_ + size);
376             stashDataSize_ = 0;
377         } else {
378             stashDataSize_ += size;
379         }
380         return PKG_SUCCESS;
381     } else {
382         return USCRIPT_ERROR_EXECUTE;
383     }
384 }
385 
ExecUpdate(PkgManager::PkgManagerPtr pkgManager,int retry,const std::string & pkgPath,PostMessageFunction postMessage)386 int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, const std::string &pkgPath,
387     PostMessageFunction postMessage)
388 {
389     UPDATER_INIT_RECORD;
390     Hpackage::HashDataVerifier scriptVerifier {pkgManager};
391     if (!scriptVerifier.LoadHashDataAndPkcs7(pkgPath)) {
392         LOG(ERROR) << "Fail to load hash data";
393         UPDATER_LAST_WORD("LoadHashDataAndPkcs7 failed", pkgPath);
394         return EXIT_VERIFY_SCRIPT_ERROR;
395     }
396     UpdaterEnv* env = new (std::nothrow) UpdaterEnv(pkgManager, postMessage, retry);
397     if (env == nullptr) {
398         LOG(ERROR) << "Fail to creat env";
399         UPDATER_LAST_WORD(EXIT_PARSE_SCRIPT_ERROR, "Fail to creat env");
400         return EXIT_PARSE_SCRIPT_ERROR;
401     }
402     int ret = 0;
403     ScriptManager* scriptManager = ScriptManager::GetScriptManager(env, &scriptVerifier);
404     if (scriptManager == nullptr) {
405         LOG(ERROR) << "Fail to creat scriptManager";
406         ScriptManager::ReleaseScriptManager();
407         delete env;
408         UPDATER_LAST_WORD(EXIT_PARSE_SCRIPT_ERROR, "Fail to creat scriptManager");
409         return EXIT_PARSE_SCRIPT_ERROR;
410     }
411 
412     UpdaterInit::GetInstance().InvokeEvent(UPDATER_BINARY_INIT_DONE_EVENT);
413 
414     pthread_t thread;
415     ret = CreateProgressThread(env, thread);
416     if (ret != 0) {
417         LOG(ERROR) << "Fail to create progress thread";
418         ScriptManager::ReleaseScriptManager();
419         delete env;
420         env = nullptr;
421         UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_THREAD, "Fail to create progress thread");
422         return USCRIPT_ERROR_CREATE_THREAD;
423     }
424 
425     for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) {
426         ret = scriptManager->ExecuteScript(i);
427         if (ret != USCRIPT_SUCCESS) {
428             LOG(ERROR) << "Fail to execute script";
429             break;
430         }
431     }
432     SetProgressExitFlag(thread);
433     ScriptManager::ReleaseScriptManager();
434     delete env;
435     env = nullptr;
436     return GetFinalBinaryResult(ret);
437 }
438 
GetWritePathAndOffset(const std::string & partitionName,std::string & writePath,uint64_t & offset,uint64_t & partitionSize)439 int UScriptInstructionRawImageWrite::GetWritePathAndOffset(const std::string &partitionName, std::string &writePath,
440     uint64_t &offset, uint64_t &partitionSize)
441 {
442 #ifdef UPDATER_USE_PTABLE
443     DevicePtable& devicePtb = DevicePtable::GetInstance();
444     Ptable::PtnInfo ptnInfo;
445     if (!devicePtb.GetPartionInfoByName(partitionName, ptnInfo)) {
446         LOG(ERROR) << "Datawriter: cannot find device path for partition \'" <<
447                 partitionName.substr(1, partitionName.size()) << "\'.";
448         return USCRIPT_ERROR_EXECUTE;
449     }
450     writePath = ptnInfo.writePath;
451     offset = ptnInfo.startAddr;
452     partitionSize = ptnInfo.partitionSize;
453 #else
454     writePath = GetBlockDeviceByMountPoint(partitionName);
455     if (writePath.empty()) {
456         LOG(ERROR) << "Datawriter: cannot find device path for partition \'" <<
457             partitionName.substr(1, partitionName.size()) << "\'.";
458         return USCRIPT_ERROR_EXECUTE;
459     }
460 
461 #ifndef UPDATER_UT
462     if (partitionName != "/userdata") {
463         std::string suffix = "";
464         GetPartitionSuffix(suffix);
465         writePath += suffix;
466     }
467     LOG(INFO) << "write partition path: " << writePath;
468 #endif
469 #endif
470     return USCRIPT_SUCCESS;
471 }
472 
ProcessUpdater(bool retry,int pipeFd,const std::string & packagePath,const std::string & keyPath)473 int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath)
474 {
475     UPDATER_INIT_RECORD;
476     UpdaterInit::GetInstance().InvokeEvent(UPDATER_BINARY_INIT_EVENT);
477     Dump::GetInstance().RegisterDump("DumpHelperLog", std::make_unique<DumpHelperLog>());
478     std::unique_ptr<FILE, decltype(&fclose)> pipeWrite(fdopen(pipeFd, "w"), fclose);
479     if (pipeWrite == nullptr) {
480         LOG(ERROR) << "Fail to fdopen, err: " << strerror(errno);
481         UPDATER_LAST_WORD(strerror(errno), "Fail to fdopen");
482         return EXIT_INVALID_ARGS;
483     }
484     int ret = -1;
485     Detail::ScopeGuard guard([&] {
486         (void)fprintf(pipeWrite.get(), "subProcessResult:%d\n", ret);
487         (void)fflush(pipeWrite.get());
488     });
489     // line buffered, make sure parent read per line.
490     setlinebuf(pipeWrite.get());
491     PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
492     if (pkgManager == nullptr) {
493         LOG(ERROR) << "pkgManager is nullptr";
494         UPDATER_LAST_WORD(EXIT_INVALID_ARGS, "pkgManager is nullptr");
495         return EXIT_INVALID_ARGS;
496     }
497 
498     std::vector<std::string> components;
499     ret = pkgManager->LoadPackage(packagePath, keyPath, components);
500     if (ret != PKG_SUCCESS) {
501         LOG(ERROR) << "Fail to load package";
502         PkgManager::ReleasePackageInstance(pkgManager);
503         UPDATER_LAST_WORD("Fail to load package", packagePath, keyPath);
504         return EXIT_INVALID_ARGS;
505     }
506 #ifdef UPDATER_USE_PTABLE
507     if (!PackagePtable::GetInstance().WritePtableWithFile()) {
508         LOG(ERROR) << "write patble with file fail";
509         PkgManager::ReleasePackageInstance(pkgManager);
510         UPDATER_LAST_WORD("Error to write ptable with file");
511         return EXIT_EXEC_SCRIPT_ERROR;
512     }
513     if (!DevicePtable::GetInstance().LoadPartitionInfo()) {
514         LOG(ERROR) << "load partition fail";
515         PkgManager::ReleasePackageInstance(pkgManager);
516         UPDATER_LAST_WORD("Error to load partition");
517         return EXIT_EXEC_SCRIPT_ERROR;
518     }
519 #endif
520 
521     ret = Updater::ExecUpdate(pkgManager, retry, packagePath,
522         [&pipeWrite](const char *cmd, const char *content) {
523             if (pipeWrite.get() != nullptr) {
524                 (void)fprintf(pipeWrite.get(), "%s:%s\n", cmd, content);
525                 (void)fflush(pipeWrite.get());
526             }
527         });
528     PkgManager::ReleasePackageInstance(pkgManager);
529 #ifndef UPDATER_UT
530     if (ret == 0) {
531         SetActiveSlot();
532     }
533 #endif
534     return ret;
535 }
536 } // Updater