• 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_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