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_image_block.h"
16 #include <cerrno>
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <sstream>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include "applypatch/block_set.h"
24 #include "applypatch/store.h"
25 #include "applypatch/transfer_manager.h"
26 #include "applypatch/partition_record.h"
27 #include "fs_manager/mount.h"
28 #include "log/log.h"
29 #include "utils.h"
30
31 using namespace Uscript;
32 using namespace Hpackage;
33 using namespace Updater;
34
35 namespace Updater {
36 constexpr int32_t SHA_CHECK_SECOND = 2;
37 constexpr int32_t SHA_CHECK_PARAMS = 3;
ExtractNewData(const PkgBuffer & buffer,size_t size,size_t start,bool isFinish,const void * context)38 static int ExtractNewData(const PkgBuffer &buffer, size_t size, size_t start, bool isFinish, const void* context)
39 {
40 void *p = const_cast<void *>(context);
41 WriterThreadInfo *info = static_cast<WriterThreadInfo *>(p);
42 uint8_t *addr = buffer.buffer;
43 while (size > 0) {
44 pthread_mutex_lock(&info->mutex);
45 while (info->writer == nullptr) {
46 if (!info->readyToWrite) {
47 LOG(WARNING) << "writer is not ready to write.";
48 pthread_mutex_unlock(&info->mutex);
49 return Hpackage::PKG_INVALID_STREAM;
50 }
51 pthread_cond_wait(&info->cond, &info->mutex);
52 }
53 pthread_mutex_unlock(&info->mutex);
54 size_t toWrite = std::min(size, info->writer->GetBlocksSize() - info->writer->GetTotalWritten());
55 // No more data to write.
56 if (toWrite == 0) {
57 break;
58 }
59 bool ret = info->writer->Write(addr, toWrite, nullptr);
60 std::ostringstream logMessage;
61 logMessage << "Write " << toWrite << " byte(s) failed";
62 if (!ret) {
63 LOG(ERROR) << logMessage.str();
64 return Hpackage::PKG_INVALID_STREAM;
65 }
66 size -= toWrite;
67 addr += toWrite;
68
69 if (info->writer->IsWriteDone()) {
70 pthread_mutex_lock(&info->mutex);
71 info->writer.reset();
72 pthread_cond_broadcast(&info->cond);
73 pthread_mutex_unlock(&info->mutex);
74 }
75 }
76 return Hpackage::PKG_SUCCESS;
77 }
78
UnpackNewData(void * arg)79 void* UnpackNewData(void *arg)
80 {
81 WriterThreadInfo *info = static_cast<WriterThreadInfo *>(arg);
82 Hpackage::PkgManager::StreamPtr stream = nullptr;
83 TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
84 if (info->newPatch.empty()) {
85 LOG(ERROR) << "new patch file name is empty. thread quit.";
86 pthread_mutex_lock(&info->mutex);
87 info->readyToWrite = false;
88 if (info->writer != nullptr) {
89 pthread_cond_broadcast(&info->cond);
90 }
91 pthread_mutex_unlock(&info->mutex);
92 return nullptr;
93 }
94 LOG(DEBUG) << "new patch file name: " << info->newPatch;
95 auto env = tm->GetGlobalParams()->env;
96 const FileInfo *file = env->GetPkgManager()->GetFileInfo(info->newPatch);
97 if (file == nullptr) {
98 LOG(ERROR) << "Cannot get file info of :" << info->newPatch;
99 pthread_mutex_lock(&info->mutex);
100 info->readyToWrite = false;
101 if (info->writer != nullptr) {
102 pthread_cond_broadcast(&info->cond);
103 }
104 pthread_mutex_unlock(&info->mutex);
105 return nullptr;
106 }
107 LOG(DEBUG) << info->newPatch << " info: size " << file->packedSize << " unpacked size " <<
108 file->unpackedSize << " name " << file->identity;
109 int32_t ret = env->GetPkgManager()->CreatePkgStream(stream, info->newPatch, ExtractNewData, info);
110 if (ret != Hpackage::PKG_SUCCESS || stream == nullptr) {
111 LOG(ERROR) << "Cannot extract " << info->newPatch << " from package.";
112 pthread_mutex_lock(&info->mutex);
113 info->readyToWrite = false;
114 if (info->writer != nullptr) {
115 pthread_cond_broadcast(&info->cond);
116 }
117 pthread_mutex_unlock(&info->mutex);
118 return nullptr;
119 }
120 ret = env->GetPkgManager()->ExtractFile(info->newPatch, stream);
121 env->GetPkgManager()->ClosePkgStream(stream);
122 pthread_mutex_lock(&info->mutex);
123 LOG(DEBUG) << "new data writer ending...";
124 // extract new data done.
125 // tell command.
126 info->readyToWrite = false;
127 UPDATER_WARING_CHECK (info->writer == nullptr, "writer is null", pthread_cond_broadcast(&info->cond));
128 pthread_mutex_unlock(&info->mutex);
129 return nullptr;
130 }
131
ReturnAndPushParam(int32_t returnValue,Uscript::UScriptContext & context)132 static int32_t ReturnAndPushParam(int32_t returnValue, Uscript::UScriptContext &context)
133 {
134 context.PushParam(returnValue);
135 return returnValue;
136 }
137
138 struct UpdateBlockInfo {
139 std::string partitionName;
140 std::string transferName;
141 std::string newDataName;
142 std::string patchDataName;
143 std::string devPath;
144 };
145
GetUpdateBlockInfo(struct UpdateBlockInfo & infos,Uscript::UScriptEnv & env,Uscript::UScriptContext & context)146 static int32_t GetUpdateBlockInfo(struct UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
147 Uscript::UScriptContext &context)
148 {
149 if (context.GetParamCount() != 4) { // 4:Determine the number of parameters
150 LOG(ERROR) << "Invalid param";
151 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context);
152 }
153
154 // Get partition Name first.
155 // Use partition name as zip file name. ${partition name}.zip
156 // load ${partition name}.zip from updater package.
157 // Try to unzip ${partition name}.zip, extract transfer.list, net.dat, patch.dat
158 size_t pos = 0;
159 int32_t ret = context.GetParam(pos++, infos.partitionName);
160 if (ret != USCRIPT_SUCCESS) {
161 LOG(ERROR) << "Error to get param 1";
162 return ret;
163 }
164 ret = context.GetParam(pos++, infos.transferName);
165 if (ret != USCRIPT_SUCCESS) {
166 LOG(ERROR) << "Error to get param 2";
167 return ret;
168 }
169 ret = context.GetParam(pos++, infos.newDataName);
170 if (ret != USCRIPT_SUCCESS) {
171 LOG(ERROR) << "Error to get param 3";
172 return ret;
173 }
174 ret = context.GetParam(pos++, infos.patchDataName);
175 if (ret != USCRIPT_SUCCESS) {
176 LOG(ERROR) << "Error to get param 4";
177 return ret;
178 }
179
180 LOG(INFO) << "ExecuteUpdateBlock::updating " << infos.partitionName << " ...";
181 infos.devPath = GetBlockDeviceByMountPoint(infos.partitionName);
182 LOG(INFO) << "ExecuteUpdateBlock::updating dev path : " << infos.devPath;
183 if (infos.devPath.empty()) {
184 LOG(ERROR) << "cannot get block device of partition";
185 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
186 }
187 return USCRIPT_SUCCESS;
188 }
189
ExecuteTransferCommand(int fd,const std::vector<std::string> & lines,Uscript::UScriptEnv & env,Uscript::UScriptContext & context,const std::string & partitionName)190 static int32_t ExecuteTransferCommand(int fd, const std::vector<std::string> &lines, Uscript::UScriptEnv &env,
191 Uscript::UScriptContext &context, const std::string &partitionName)
192 {
193 TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
194 auto globalParams = tm->GetGlobalParams();
195 auto writerThreadInfo = globalParams->writerThreadInfo.get();
196
197 globalParams->storeBase = "/data/updater/update_tmp";
198 globalParams->retryFile = std::string("/data/updater") + partitionName + "_retry";
199 LOG(INFO) << "Store base path is " << globalParams->storeBase;
200 int32_t ret = Store::CreateNewSpace(globalParams->storeBase, !globalParams->env->IsRetry());
201 if (ret == -1) {
202 LOG(ERROR) << "Error to create new store space";
203 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
204 }
205 globalParams->storeCreated = ret;
206
207 if (!tm->CommandsParser(fd, lines)) {
208 return USCRIPT_ERROR_EXECUTE;
209 }
210 pthread_mutex_lock(&writerThreadInfo->mutex);
211 if (writerThreadInfo->readyToWrite) {
212 LOG(WARNING) << "New data writer thread is still available...";
213 }
214
215 writerThreadInfo->readyToWrite = false;
216 pthread_cond_broadcast(&writerThreadInfo->cond);
217 pthread_mutex_unlock(&writerThreadInfo->mutex);
218 ret = pthread_join(globalParams->thread, nullptr);
219 std::ostringstream logMessage;
220 logMessage << "pthread join returned with " << ret;
221 if (ret != 0) {
222 LOG(WARNING) << logMessage.str();
223 }
224 if (globalParams->storeCreated != -1) {
225 Store::DoFreeSpace(globalParams->storeBase);
226 }
227 return USCRIPT_SUCCESS;
228 }
229
InitThread(const struct UpdateBlockInfo & infos,Uscript::UScriptEnv & env,Uscript::UScriptContext & context)230 static int InitThread(const struct UpdateBlockInfo &infos, Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
231 {
232 TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
233 auto globalParams = tm->GetGlobalParams();
234 auto writerThreadInfo = globalParams->writerThreadInfo.get();
235 writerThreadInfo->readyToWrite = true;
236 pthread_mutex_init(&writerThreadInfo->mutex, nullptr);
237 pthread_cond_init(&writerThreadInfo->cond, nullptr);
238 pthread_attr_t attr;
239 pthread_attr_init(&attr);
240 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
241 writerThreadInfo->newPatch = infos.newDataName;
242 int error = pthread_create(&globalParams->thread, &attr, UnpackNewData, writerThreadInfo);
243 return error;
244 }
245
ExtractDiffPackageAndLoad(const UpdateBlockInfo & infos,Uscript::UScriptEnv & env,Uscript::UScriptContext & context)246 static int32_t ExtractDiffPackageAndLoad(const UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
247 Uscript::UScriptContext &context)
248 {
249 Hpackage::PkgManager::StreamPtr outStream = nullptr;
250 LOG(DEBUG) << "partitionName is " << infos.partitionName;
251 const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.partitionName);
252 if (info == nullptr) {
253 LOG(ERROR) << "Error to get file info";
254 return USCRIPT_ERROR_EXECUTE;
255 }
256 std::string diffPackage = std::string("/data/updater") + infos.partitionName;
257 int32_t ret = env.GetPkgManager()->CreatePkgStream(outStream,
258 diffPackage, info->unpackedSize, PkgStream::PkgStreamType_Write);
259 if (outStream == nullptr) {
260 LOG(ERROR) << "Error to create output stream";
261 return USCRIPT_ERROR_EXECUTE;
262 }
263
264 ret = env.GetPkgManager()->ExtractFile(infos.partitionName, outStream);
265 if (ret != USCRIPT_SUCCESS) {
266 LOG(ERROR) << "Error to extract file";
267 env.GetPkgManager()->ClosePkgStream(outStream);
268 return USCRIPT_ERROR_EXECUTE;
269 }
270 env.GetPkgManager()->ClosePkgStream(outStream);
271 std::string diffPackageZip = diffPackage + ".zip";
272 if (rename(diffPackage.c_str(), diffPackageZip.c_str()) != 0) {
273 LOG(ERROR) << "rename failed";
274 return USCRIPT_ERROR_EXECUTE;
275 }
276 LOG(DEBUG) << "Rename " << diffPackage << " to zip\nExtract " << diffPackage << " done\nReload " << diffPackageZip;
277 std::vector<std::string> diffPackageComponents;
278 ret = env.GetPkgManager()->LoadPackage(diffPackageZip, Updater::Utils::GetCertName(), diffPackageComponents);
279 if (diffPackageComponents.size() < 1) {
280 LOG(ERROR) << "Diff package is empty";
281 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context);
282 }
283 return USCRIPT_SUCCESS;
284 }
285
DoExecuteUpdateBlock(const UpdateBlockInfo & infos,Uscript::UScriptEnv & env,Hpackage::PkgManager::StreamPtr & outStream,const std::vector<std::string> & lines,Uscript::UScriptContext & context)286 static int32_t DoExecuteUpdateBlock(const UpdateBlockInfo &infos, Uscript::UScriptEnv &env,
287 Hpackage::PkgManager::StreamPtr &outStream, const std::vector<std::string> &lines, Uscript::UScriptContext &context)
288 {
289 int fd = open(infos.devPath.c_str(), O_RDWR | O_LARGEFILE);
290 if (fd == -1) {
291 LOG(ERROR) << "Failed to open block";
292 env.GetPkgManager()->ClosePkgStream(outStream);
293 return USCRIPT_ERROR_EXECUTE;
294 }
295 int32_t ret = ExecuteTransferCommand(fd, lines, env, context, infos.partitionName);
296 fsync(fd);
297 close(fd);
298 fd = -1;
299 env.GetPkgManager()->ClosePkgStream(outStream);
300 if (ret == USCRIPT_SUCCESS) {
301 PartitionRecord::GetInstance().RecordPartitionUpdateStatus(infos.partitionName, true);
302 }
303 return ret;
304 }
305
ExecuteUpdateBlock(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)306 static int32_t ExecuteUpdateBlock(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
307 {
308 UpdateBlockInfo infos {};
309 UPDATER_CHECK_ONLY_RETURN(!GetUpdateBlockInfo(infos, env, context), return USCRIPT_ERROR_EXECUTE);
310 UPDATER_ERROR_CHECK(env.GetPkgManager() != nullptr, "Error to get pkg manager", return USCRIPT_ERROR_EXECUTE);
311
312 if (env.IsRetry()) {
313 LOG(DEBUG) << "Retry updater, check if current partition updatered already during last time";
314 bool isUpdated = PartitionRecord::GetInstance().IsPartitionUpdated(infos.partitionName);
315 if (isUpdated) {
316 LOG(INFO) << infos.partitionName << " already updated, skip";
317 return USCRIPT_SUCCESS;
318 }
319 }
320
321 int32_t ret = ExtractDiffPackageAndLoad(infos, env, context);
322 UPDATER_CHECK_ONLY_RETURN(ret == USCRIPT_SUCCESS, return USCRIPT_ERROR_EXECUTE);
323
324 const FileInfo *info = env.GetPkgManager()->GetFileInfo(infos.transferName);
325 UPDATER_ERROR_CHECK(info != nullptr, "GetFileInfo fail", return USCRIPT_ERROR_EXECUTE);
326 Hpackage::PkgManager::StreamPtr outStream = nullptr;
327 ret = env.GetPkgManager()->CreatePkgStream(outStream,
328 infos.transferName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
329 ret = env.GetPkgManager()->ExtractFile(infos.transferName, outStream);
330 uint8_t *transferListBuffer = nullptr;
331 size_t transferListSize = 0;
332 ret = outStream->GetBuffer(transferListBuffer, transferListSize);
333 TransferManagerPtr tm = TransferManager::GetTransferManagerInstance();
334 auto globalParams = tm->GetGlobalParams();
335 /* Save Script Env to transfer manager */
336 globalParams->env = &env;
337 std::vector<std::string> lines =
338 Updater::Utils::SplitString(std::string(reinterpret_cast<const char*>(transferListBuffer)), "\n");
339 // Close stream opened before.
340 env.GetPkgManager()->ClosePkgStream(outStream);
341
342 LOG(INFO) << "Start unpack new data thread done. Get patch data: " << infos.patchDataName;
343 info = env.GetPkgManager()->GetFileInfo(infos.patchDataName);
344 UPDATER_ERROR_CHECK(info != nullptr, "GetFileInfo fail", return USCRIPT_ERROR_EXECUTE);
345
346 ret = env.GetPkgManager()->CreatePkgStream(outStream,
347 infos.patchDataName, info->unpackedSize, PkgStream::PkgStreamType_MemoryMap);
348 UPDATER_ERROR_CHECK(outStream != nullptr, "Error to create output stream", return USCRIPT_ERROR_EXECUTE);
349 ret = env.GetPkgManager()->ExtractFile(infos.patchDataName, outStream);
350 UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Error to extract file",
351 env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
352 outStream->GetBuffer(globalParams->patchDataBuffer, globalParams->patchDataSize);
353 LOG(DEBUG) << "Patch data size is: " << globalParams->patchDataSize;
354
355 LOG(INFO) << "Ready to start a thread to handle new data processing";
356 UPDATER_ERROR_CHECK (InitThread(infos, env, context) == 0, "Failed to create pthread",
357 env.GetPkgManager()->ClosePkgStream(outStream); return USCRIPT_ERROR_EXECUTE);
358
359 ret = DoExecuteUpdateBlock(infos, env, outStream, lines, context);
360 TransferManager::ReleaseTransferManagerInstance(tm);
361 return ret;
362 }
363
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)364 int32_t UScriptInstructionBlockUpdate::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
365 {
366 int32_t result = ExecuteUpdateBlock(env, context);
367 context.PushParam(result);
368 return result;
369 }
370
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)371 int32_t UScriptInstructionBlockCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
372 {
373 UPDATER_ERROR_CHECK(context.GetParamCount() == 1, "Invalid param",
374 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context));
375 if (env.IsRetry()) {
376 return ReturnAndPushParam(USCRIPT_SUCCESS, context);
377 }
378 std::string partitionName;
379 int32_t ret = context.GetParam(0, partitionName);
380 UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
381 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
382 auto devPath = GetBlockDeviceByMountPoint(partitionName);
383 LOG(INFO) << "UScriptInstructionBlockCheck::dev path : " << devPath;
384 UPDATER_ERROR_CHECK(!devPath.empty(), "cannot get block device of partition",
385 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
386 int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
387 UPDATER_ERROR_CHECK(fd != -1, "Failed to open file",
388 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
389 std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
390 BlockSet blk0(std::vector<BlockPair> {BlockPair{0, 1}});
391
392 size_t pos = 0;
393 std::vector<BlockPair>::iterator it = blk0.Begin();
394 for (; it != blk0.End(); ++it) {
395 LOG(INFO) << "BlockSet::ReadDataFromBlock lseek64";
396 ret = lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET);
397 UPDATER_ERROR_CHECK(ret != -1, "Failed to seek",
398 close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
399 size_t size = (it->second - it->first) * H_BLOCK_SIZE;
400 LOG(INFO) << "BlockSet::ReadDataFromBlock Read " << size << " from block";
401 UPDATER_ERROR_CHECK(Utils::ReadFully(fd, block_buff.data() + pos, size), "Failed to read",
402 close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
403 pos += size;
404 }
405
406 time_t mountTime = *reinterpret_cast<uint32_t *>(&block_buff[0x400 + 0x2C]);
407 uint16_t mountCount = *reinterpret_cast<uint16_t *>(&block_buff[0x400 + 0x34]);
408
409 if (mountCount > 0) {
410 std::ostringstream ostr;
411 ostr << "Device was remounted R/W " << mountCount << "times\nLast remount happened on " <<
412 ctime(&mountTime) << std::endl;
413 std::string message = ostr.str();
414 env.PostMessage("ui_log", message);
415 }
416 LOG(INFO) << "UScriptInstructionBlockCheck::Execute Success";
417 context.PushParam(USCRIPT_SUCCESS);
418 close(fd);
419 return USCRIPT_SUCCESS;
420 }
421
Execute(Uscript::UScriptEnv & env,Uscript::UScriptContext & context)422 int32_t UScriptInstructionShaCheck::Execute(Uscript::UScriptEnv &env, Uscript::UScriptContext &context)
423 {
424 UPDATER_ERROR_CHECK(context.GetParamCount() == SHA_CHECK_PARAMS, "Invalid param",
425 return ReturnAndPushParam(USCRIPT_INVALID_PARAM, context));
426 UPDATER_CHECK_ONLY_RETURN(!env.IsRetry(), return ReturnAndPushParam(USCRIPT_SUCCESS, context));
427
428 std::string partitionName;
429 int32_t ret = context.GetParam(0, partitionName);
430 UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
431 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
432 std::string blockPairs;
433 ret = context.GetParam(1, blockPairs);
434 UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
435 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
436 std::string contrastSha;
437 ret = context.GetParam(SHA_CHECK_SECOND, contrastSha);
438 UPDATER_ERROR_CHECK(ret == USCRIPT_SUCCESS, "Failed to get param",
439 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
440 auto devPath = GetBlockDeviceByMountPoint(partitionName);
441 LOG(INFO) << "UScriptInstructionShaCheck::dev path : " << devPath;
442 UPDATER_ERROR_CHECK(!devPath.empty(), "cannot get block device of partition",
443 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
444 int fd = open(devPath.c_str(), O_RDWR | O_LARGEFILE);
445 UPDATER_ERROR_CHECK(fd != -1, "Failed to open file",
446 return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
447
448 BlockSet blk;
449 blk.ParserAndInsert(blockPairs);
450 std::vector<uint8_t> block_buff(H_BLOCK_SIZE);
451
452 SHA256_CTX ctx;
453 SHA256_Init(&ctx);
454
455 std::vector<BlockPair>::iterator it = blk.Begin();
456 for (; it != blk.End(); ++it) {
457 ret = lseek64(fd, static_cast<off64_t>(it->first * H_BLOCK_SIZE), SEEK_SET);
458 UPDATER_ERROR_CHECK(ret != -1, "Failed to seek",
459 close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
460
461 for (size_t i = it->first; i < it->second; ++i) {
462 UPDATER_ERROR_CHECK(Utils::ReadFully(fd, block_buff.data(), H_BLOCK_SIZE), "Failed to read",
463 close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
464 SHA256_Update(&ctx, block_buff.data(), H_BLOCK_SIZE);
465 }
466 }
467 uint8_t digest[SHA256_DIGEST_LENGTH];
468 SHA256_Final(digest, &ctx);
469 std::string resultSha = Utils::ConvertSha256Hex(digest, SHA256_DIGEST_LENGTH);
470 UPDATER_ERROR_CHECK(resultSha == contrastSha, "Different sha256, cannot continue",
471 close(fd); return ReturnAndPushParam(USCRIPT_ERROR_EXECUTE, context));
472 LOG(INFO) << "UScriptInstructionShaCheck::Execute Success";
473 context.PushParam(USCRIPT_SUCCESS);
474 close(fd);
475 return USCRIPT_SUCCESS;
476 }
477 }
478