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