• 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         "is_updater_mode"
88     };
89     return updaterCmds;
90 }
91 
CreateInstructionInstance(UScriptInstructionPtr & instr,const std::string & name)92 int32_t UpdaterInstructionFactory::CreateInstructionInstance(UScriptInstructionPtr& instr,
93     const std::string& name)
94 {
95     if (name == "sha_check") {
96         instr = new UScriptInstructionShaCheck();
97     } else if (name == "first_block_check") {
98         instr = new UScriptInstructionBlockCheck();
99     } else if (name == "block_update") {
100         instr = new UScriptInstructionBlockUpdate();
101     } else if (name == "raw_image_write") {
102         instr = new UScriptInstructionRawImageWrite();
103     } else if (name == "update_partitions") {
104         instr = new UpdatePartitions();
105     } else if (name == "image_patch") {
106         instr = new USInstrImagePatch();
107     } else if (name == "image_sha_check") {
108         instr = new USInstrImageShaCheck();
109     } else if (name == "pkg_extract") {
110         instr = new UScriptInstructionPkgExtract();
111     } else if (name == "pkg_extract_no_ret") {
112         instr = new UScriptInstructionPkgExtractRetSuc();
113     } else if (name == "update_from_bin") {
114         instr = new UScriptInstructionBinFlowWrite();
115     } else if (name == "is_updater_mode") {
116         instr = new UScriptInstructionIsUpdaterMode();
117     }
118     return USCRIPT_SUCCESS;
119 }
120 
RawImageWriteProcessor(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)121 int UScriptInstructionRawImageWrite::RawImageWriteProcessor(const PkgBuffer &buffer, size_t size, size_t start,
122                                                             bool isFinish, const void* context)
123 {
124     void *p = const_cast<void *>(context);
125     DataWriter *writer = static_cast<DataWriter *>(p);
126     if (writer == nullptr) {
127         LOG(ERROR) << "Data writer is null";
128         return PKG_INVALID_STREAM;
129     }
130 
131     // maybe extract from package is finished. just return.
132     if (buffer.buffer == nullptr || size == 0) {
133         return PKG_SUCCESS;
134     }
135 
136     bool ret = writer->Write(const_cast<uint8_t*>(buffer.buffer), size, nullptr);
137     if (!ret) {
138         LOG(ERROR) << "Write " << size << " byte(s) failed";
139         return PKG_INVALID_STREAM;
140     }
141 
142     if (totalSize_ != 0) {
143         readSize_ += size;
144         writer->GetUpdaterEnv()->PostMessage("set_progress", std::to_string((float)readSize_ / totalSize_));
145     }
146 
147     return PKG_SUCCESS;
148 }
149 
WriteRawImage(const std::string & partitionName,const std::unique_ptr<DataWriter> & writer,uint64_t partitionSize,Uscript::UScriptEnv & env)150 bool UScriptInstructionRawImageWrite::WriteRawImage(const std::string &partitionName,
151     const std::unique_ptr<DataWriter> &writer, [[maybe_unused]] uint64_t partitionSize, Uscript::UScriptEnv &env)
152 {
153     UPDATER_INIT_RECORD;
154     // Extract partition information
155     const FileInfo *info = env.GetPkgManager()->GetFileInfo(partitionName);
156     if (info == nullptr) {
157         LOG(ERROR) << "Error to get file info";
158         UPDATER_LAST_WORD("Error to get file info", partitionName);
159         return false;
160     }
161     totalSize_ = info->unpackedSize;
162 #ifdef UPDATER_USE_PTABLE
163     if (partitionSize < totalSize_) {
164         LOG(ERROR) << "partition size: " << partitionSize << " is short than image size: " << totalSize_;
165         UPDATER_LAST_WORD(false);
166         return false;
167     }
168 #endif
169 
170     Hpackage::PkgManager::StreamPtr outStream = nullptr;
171     int ret = env.GetPkgManager()->CreatePkgStream(outStream,
172         partitionName, RawImageWriteProcessor, writer.get());
173     if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
174         LOG(ERROR) << "Error to create output stream";
175         UPDATER_LAST_WORD("Error to create output stream", partitionName);
176         return false;
177     }
178 
179     ret = env.GetPkgManager()->ExtractFile(partitionName, outStream);
180     if (ret != USCRIPT_SUCCESS) {
181         LOG(ERROR) << "Error to extract file";
182         env.GetPkgManager()->ClosePkgStream(outStream);
183         UPDATER_LAST_WORD("Error to extract file", partitionName);
184         return false;
185     }
186     env.GetPkgManager()->ClosePkgStream(outStream);
187     return true;
188 }
189 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)190 int32_t UScriptInstructionRawImageWrite::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
191 {
192     UPDATER_INIT_RECORD;
193     std::string partitionName;
194     int32_t ret = context.GetParam(0, partitionName);
195     if (ret != USCRIPT_SUCCESS) {
196         LOG(ERROR) << "Error to get partitionName";
197         UPDATER_LAST_WORD(ret, "Error to get partitionName");
198         return ret;
199     }
200 
201     if (env.IsRetry()) {
202         LOG(DEBUG) << "Retry updater, check if current partition updated already during last time";
203         if (PartitionRecord::GetInstance().IsPartitionUpdated(partitionName)) {
204             LOG(INFO) << partitionName << " already updated, skip";
205             return USCRIPT_SUCCESS;
206         }
207     }
208     LOG(INFO) << "UScriptInstructionRawImageWrite::Execute " << partitionName;
209     if (env.GetPkgManager() == nullptr) {
210         LOG(ERROR) << "Error to get pkg manager";
211         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "UScriptInstructionRawImageWrite::Execute " + partitionName);
212         return USCRIPT_ERROR_EXECUTE;
213     }
214 
215     std::string writePath;
216     uint64_t offset = 0;
217     uint64_t partitionSize = 0;
218     if (GetWritePathAndOffset(partitionName, writePath, offset, partitionSize) != USCRIPT_SUCCESS) {
219         LOG(ERROR) << "Get partition:%s WritePathAndOffset fail \'" <<
220             partitionName.substr(1, partitionName.size()) << "\'.";
221         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "GetWritePathAndOffset fail " + partitionName);
222         return USCRIPT_ERROR_EXECUTE;
223     }
224 
225     std::unique_ptr<DataWriter> writer = DataWriter::CreateDataWriter(WRITE_RAW, writePath,
226         static_cast<UpdaterEnv *>(&env), offset);
227     if (writer == nullptr) {
228         LOG(ERROR) << "Error to create writer";
229         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "Error to create writer");
230         return USCRIPT_ERROR_EXECUTE;
231     }
232     if (!WriteRawImage(partitionName, writer, partitionSize, env)) {
233         DataWriter::ReleaseDataWriter(writer);
234         UPDATER_LAST_WORD(USCRIPT_ERROR_EXECUTE, "WriteRawImage failed");
235         return USCRIPT_ERROR_EXECUTE;
236     }
237     PartitionRecord::GetInstance().RecordPartitionUpdateStatus(partitionName, true);
238     DataWriter::ReleaseDataWriter(writer);
239     totalSize_ = 0;
240     readSize_ = 0;
241     LOG(INFO) << "UScriptInstructionRawImageWrite finish";
242     return USCRIPT_SUCCESS;
243 }
244 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)245 int32_t UScriptInstructionPkgExtract::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
246 {
247     UPDATER_INIT_RECORD;
248     std::string pkgFileName;
249     int32_t ret = context.GetParam(0, pkgFileName);
250     if (ret != USCRIPT_SUCCESS) {
251         LOG(ERROR) << "Error to get pkgFileName";
252         UPDATER_LAST_WORD(ret, "Error to get pkgFileName");
253         return ret;
254     }
255 
256     std::string destPath;
257     ret = context.GetParam(1, destPath);
258     if (ret != USCRIPT_SUCCESS) {
259         LOG(ERROR) << "Error to get destPath";
260         UPDATER_LAST_WORD(ret, "Error to get destPath");
261         return ret;
262     }
263 
264     LOG(INFO) << "UScriptInstructionPkgExtract::Execute " << pkgFileName;
265     PkgManager::PkgManagerPtr manager = env.GetPkgManager();
266     if (manager == nullptr) {
267         LOG(ERROR) << "Error to get pkg manager";
268         UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM, "Error to get pkg manager");
269         return USCRIPT_INVALID_PARAM;
270     }
271 
272     const FileInfo *info = manager->GetFileInfo(pkgFileName);
273     if (info == nullptr) {
274         LOG(ERROR) << "Error to get file info";
275         UPDATER_LAST_WORD("Error to get file info", pkgFileName);
276         return USCRIPT_INVALID_PARAM;
277     }
278 
279     Hpackage::PkgManager::StreamPtr outStream = nullptr;
280     ret = manager->CreatePkgStream(outStream, destPath + "/" + pkgFileName, info->unpackedSize,
281         PkgStream::PkgStreamType_Write);
282     if (ret != USCRIPT_SUCCESS) {
283         LOG(ERROR) << "Error to create output stream";
284         UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM, "Error to create output stream");
285         return USCRIPT_ERROR_EXECUTE;
286     }
287 
288     ret = manager->ExtractFile(pkgFileName, outStream);
289     if (ret != USCRIPT_SUCCESS) {
290         LOG(ERROR) << "Error to extract file";
291         manager->ClosePkgStream(outStream);
292         UPDATER_LAST_WORD("Error to create output stream", pkgFileName);
293         return USCRIPT_ERROR_EXECUTE;
294     }
295 
296     manager->ClosePkgStream(outStream);
297     LOG(INFO)<<"UScriptInstructionPkgExtract finish";
298     return ret;
299 }
300 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)301 int32_t UScriptInstructionPkgExtractRetSuc::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
302 {
303     std::unique_lock<std::mutex> lock(extractNoRetMutex_);
304     int32_t ret = UScriptInstructionPkgExtract::Execute(env, context);
305     if (ret != USCRIPT_SUCCESS) {
306         LOG(ERROR) << "Error to extract file, ret = " << ret;
307     }
308     return USCRIPT_SUCCESS;
309 }
310 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)311 int32_t UScriptInstructionUpdateFromBin::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
312 {
313     std::string upgradeFileName;
314     int32_t ret = context.GetParam(0, upgradeFileName);
315     if (ret != USCRIPT_SUCCESS) {
316         LOG(ERROR) << "Error to get partitionName";
317         return ret;
318     }
319 
320     LOG(INFO) << "UScriptInstructionUpdateFromBin::Execute " << upgradeFileName;
321 
322     PkgManager::PkgManagerPtr pkgManager = env.GetPkgManager();
323     if (pkgManager == nullptr) {
324         LOG(ERROR) << "Error to get pkg manager";
325         return USCRIPT_INVALID_PARAM;
326     }
327 
328     RingBuffer ringBuffer;
329     if (!ringBuffer.Init(STASH_BUFFER_SIZE, BUFFER_NUM)) {
330         LOG(ERROR) << "Error to get ringbuffer";
331         return USCRIPT_INVALID_PARAM;
332     }
333 
334     PkgManager::StreamPtr outStream = nullptr;
335     ret = pkgManager->CreatePkgStream(outStream, upgradeFileName, UnCompressDataProducer, &ringBuffer);
336     if (ret != USCRIPT_SUCCESS || outStream == nullptr) {
337         LOG(ERROR) << "Error to create output stream";
338         return USCRIPT_INVALID_PARAM;
339     }
340 
341     ret = pkgManager->ExtractFile(upgradeFileName, outStream);
342     if (ret != USCRIPT_SUCCESS) {
343         LOG(ERROR) << "Error to extract" << upgradeFileName;
344         pkgManager->ClosePkgStream(outStream);
345         return USCRIPT_ERROR_EXECUTE;
346     }
347     pkgManager->ClosePkgStream(outStream);
348     return USCRIPT_ERROR_EXECUTE;
349 }
350 
UnCompressDataProducer(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)351 int UScriptInstructionUpdateFromBin::UnCompressDataProducer(const PkgBuffer &buffer, size_t size, size_t start,
352                                                             bool isFinish, const void* context)
353 {
354     static PkgBuffer stashBuffer(STASH_BUFFER_SIZE);
355     size_t bufferStart = 0;
356     void *p = const_cast<void *>(context);
357     RingBuffer *ringBuffer = static_cast<RingBuffer *>(p);
358     if (ringBuffer == nullptr) {
359         LOG(ERROR) << "ring buffer is nullptr";
360         return PKG_INVALID_STREAM;
361     }
362 
363     while (stashDataSize_ + size >= STASH_BUFFER_SIZE) {
364         size_t readLen = STASH_BUFFER_SIZE - stashDataSize_;
365         if (memcpy_s(stashBuffer.buffer + stashDataSize_, readLen, buffer.buffer + bufferStart, readLen) != 0) {
366                 return USCRIPT_ERROR_EXECUTE;
367         }
368         ringBuffer->Push(stashBuffer.buffer, STASH_BUFFER_SIZE);
369         stashDataSize_ = 0;
370         size -= readLen;
371         bufferStart += readLen;
372     }
373     if (size == 0 && stashDataSize_ == 0) {
374         return PKG_SUCCESS;
375     } else if (size == 0 || memcpy_s(stashBuffer.buffer + stashDataSize_, STASH_BUFFER_SIZE - stashDataSize_,
376         buffer.buffer + bufferStart, size) == 0) {
377         if (isFinish) {
378             ringBuffer->Push(stashBuffer.buffer, stashDataSize_ + size);
379             stashDataSize_ = 0;
380         } else {
381             stashDataSize_ += size;
382         }
383         return PKG_SUCCESS;
384     } else {
385         return USCRIPT_ERROR_EXECUTE;
386     }
387 }
388 
ExecUpdate(PkgManager::PkgManagerPtr pkgManager,int retry,const std::string & pkgPath,PostMessageFunction postMessage)389 int ExecUpdate(PkgManager::PkgManagerPtr pkgManager, int retry, const std::string &pkgPath,
390     PostMessageFunction postMessage)
391 {
392     UPDATER_INIT_RECORD;
393     Hpackage::HashDataVerifier scriptVerifier {pkgManager};
394     if (!scriptVerifier.LoadHashDataAndPkcs7(pkgPath)) {
395         LOG(ERROR) << "Fail to load hash data";
396         UPDATER_LAST_WORD("LoadHashDataAndPkcs7 failed", pkgPath);
397         return EXIT_VERIFY_SCRIPT_ERROR;
398     }
399     UpdaterEnv* env = new (std::nothrow) UpdaterEnv(pkgManager, postMessage, retry);
400     if (env == nullptr) {
401         LOG(ERROR) << "Fail to creat env";
402         UPDATER_LAST_WORD(EXIT_PARSE_SCRIPT_ERROR, "Fail to creat env");
403         return EXIT_PARSE_SCRIPT_ERROR;
404     }
405     int ret = 0;
406     ScriptManager* scriptManager = ScriptManager::GetScriptManager(env, &scriptVerifier);
407     if (scriptManager == nullptr) {
408         LOG(ERROR) << "Fail to creat scriptManager";
409         ScriptManager::ReleaseScriptManager();
410         delete env;
411         UPDATER_LAST_WORD(EXIT_PARSE_SCRIPT_ERROR, "Fail to creat scriptManager");
412         return EXIT_PARSE_SCRIPT_ERROR;
413     }
414 
415     UpdaterInit::GetInstance().InvokeEvent(UPDATER_BINARY_INIT_DONE_EVENT);
416 
417     pthread_t thread;
418     ret = CreateProgressThread(env, thread);
419     if (ret != 0) {
420         LOG(ERROR) << "Fail to create progress thread";
421         ScriptManager::ReleaseScriptManager();
422         delete env;
423         env = nullptr;
424         UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_THREAD, "Fail to create progress thread");
425         return USCRIPT_ERROR_CREATE_THREAD;
426     }
427 
428     for (int32_t i = 0; i < ScriptManager::MAX_PRIORITY; i++) {
429         ret = scriptManager->ExecuteScript(i);
430         if (ret != USCRIPT_SUCCESS) {
431             LOG(ERROR) << "Fail to execute script";
432             break;
433         }
434     }
435     SetProgressExitFlag(thread);
436     ScriptManager::ReleaseScriptManager();
437     delete env;
438     env = nullptr;
439     return GetFinalBinaryResult(ret);
440 }
441 
GetWritePathAndOffset(const std::string & partitionName,std::string & writePath,uint64_t & offset,uint64_t & partitionSize)442 int UScriptInstructionRawImageWrite::GetWritePathAndOffset(const std::string &partitionName, std::string &writePath,
443     uint64_t &offset, uint64_t &partitionSize)
444 {
445 #ifdef UPDATER_USE_PTABLE
446     DevicePtable& devicePtb = DevicePtable::GetInstance();
447     Ptable::PtnInfo ptnInfo;
448     if (!devicePtb.GetPartionInfoByName(partitionName, ptnInfo)) {
449         LOG(ERROR) << "Datawriter: cannot find device path for partition \'" <<
450                 partitionName.substr(1, partitionName.size()) << "\'.";
451         return USCRIPT_ERROR_EXECUTE;
452     }
453     writePath = ptnInfo.writePath;
454     offset = ptnInfo.startAddr;
455     partitionSize = ptnInfo.partitionSize;
456 #else
457     writePath = GetBlockDeviceByMountPoint(partitionName);
458     if (writePath.empty()) {
459         LOG(ERROR) << "Datawriter: cannot find device path for partition \'" <<
460             partitionName.substr(1, partitionName.size()) << "\'.";
461         return USCRIPT_ERROR_EXECUTE;
462     }
463 
464 #ifndef UPDATER_UT
465     if (partitionName != "/userdata") {
466         std::string suffix = Utils::GetUpdateSuffix();
467         writePath += suffix;
468     }
469     LOG(INFO) << "write partition path: " << writePath;
470 #endif
471 #endif
472     return USCRIPT_SUCCESS;
473 }
474 
ProcessUpdater(bool retry,int pipeFd,const std::string & packagePath,const std::string & keyPath)475 int ProcessUpdater(bool retry, int pipeFd, const std::string &packagePath, const std::string &keyPath)
476 {
477     UPDATER_INIT_RECORD;
478     UpdaterInit::GetInstance().InvokeEvent(UPDATER_BINARY_INIT_EVENT);
479     Dump::GetInstance().RegisterDump("DumpHelperLog", std::make_unique<DumpHelperLog>());
480     std::unique_ptr<FILE, decltype(&fclose)> pipeWrite(fdopen(pipeFd, "w"), fclose);
481     if (pipeWrite == nullptr) {
482         LOG(ERROR) << "Fail to fdopen, err: " << strerror(errno);
483         UPDATER_LAST_WORD(strerror(errno), "Fail to fdopen");
484         return EXIT_INVALID_ARGS;
485     }
486     int ret = -1;
487     Detail::ScopeGuard guard([&] {
488         (void)fprintf(pipeWrite.get(), "subProcessResult:%d\n", ret);
489         (void)fflush(pipeWrite.get());
490     });
491     // line buffered, make sure parent read per line.
492     setlinebuf(pipeWrite.get());
493     PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
494     if (pkgManager == nullptr) {
495         LOG(ERROR) << "pkgManager is nullptr";
496         UPDATER_LAST_WORD(EXIT_INVALID_ARGS, "pkgManager is nullptr");
497         return EXIT_INVALID_ARGS;
498     }
499 
500     std::vector<std::string> components;
501     ret = pkgManager->LoadPackage(packagePath, keyPath, components);
502     if (ret != PKG_SUCCESS) {
503         LOG(ERROR) << "Fail to load package";
504         PkgManager::ReleasePackageInstance(pkgManager);
505         UPDATER_LAST_WORD("Fail to load package", packagePath, keyPath);
506         return EXIT_INVALID_ARGS;
507     }
508 #ifdef UPDATER_USE_PTABLE
509     if (!PackagePtable::GetInstance().WritePtableWithFile()) {
510         LOG(ERROR) << "write patble with file fail";
511         PkgManager::ReleasePackageInstance(pkgManager);
512         UPDATER_LAST_WORD("Error to write ptable with file");
513         return EXIT_EXEC_SCRIPT_ERROR;
514     }
515     if (!DevicePtable::GetInstance().LoadPartitionInfo()) {
516         LOG(ERROR) << "load partition fail";
517         PkgManager::ReleasePackageInstance(pkgManager);
518         UPDATER_LAST_WORD("Error to load partition");
519         return EXIT_EXEC_SCRIPT_ERROR;
520     }
521 #endif
522 
523     ret = Updater::ExecUpdate(pkgManager, retry, packagePath,
524         [&pipeWrite](const char *cmd, const char *content) {
525             if (pipeWrite.get() != nullptr) {
526                 (void)fprintf(pipeWrite.get(), "%s:%s\n", cmd, content);
527                 (void)fflush(pipeWrite.get());
528             }
529         });
530     PkgManager::ReleasePackageInstance(pkgManager);
531     return ret;
532 }
533 
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)534 int32_t UScriptInstructionIsUpdaterMode::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
535 {
536     int32_t ret = Utils::IsUpdaterMode() ? USCRIPT_UPDATER_MODE_VALUE : USCRIPT_SUCCESS;
537     context.PushParam(ret);
538     return ret;
539 }
540 } // Updater
541