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 16#include "blocks_patch.h" 17#include <cstdio> 18#include <iostream> 19#include <vector> 20#include "diffpatch.h" 21 22using namespace Hpackage; 23using namespace std; 24 25namespace UpdatePatch { 26#define PATCH_MIN std::char_traits<char>::length(BSDIFF_MAGIC) + sizeof(int64_t) * 3 27#define GET_BYTE_FROM_BUFFER(v, index, buffer) ((v) * 256 + (buffer)[index]) 28constexpr uint8_t BUFFER_MASK = 0x80; 29 30static int64_t ReadLE64(const uint8_t *buffer) 31{ 32 if (buffer == nullptr) { 33 return 0; 34 } 35 int64_t y = 0; 36 int32_t index = static_cast<int32_t>(sizeof(int64_t)) - 1; 37 y = buffer[index] & static_cast<uint8_t>(~BUFFER_MASK); 38 index--; 39 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 40 index--; 41 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 42 index--; 43 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 44 index--; 45 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 46 index--; 47 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 48 index--; 49 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 50 index--; 51 y = GET_BYTE_FROM_BUFFER(y, index, buffer); 52 53 index = static_cast<int32_t>(sizeof(int64_t)); 54 if (buffer[index - 1] & BUFFER_MASK) { 55 y = -y; 56 } 57 return y; 58} 59 60int32_t BlocksPatch::ApplyPatch() 61{ 62 int64_t controlDataSize = 0; 63 int64_t diffDataSize = 0; 64 int32_t ret = ReadHeader(controlDataSize, diffDataSize, newSize_); 65 if (ret != 0) { 66 PATCH_LOGE("Failed to read header "); 67 return -1; 68 } 69 70 while (newOffset_ < newSize_) { 71 ControlData ctrlData {}; 72 ret = ReadControlData(ctrlData); 73 if (ret != 0) { 74 PATCH_LOGE("Failed to read control data"); 75 return ret; 76 } 77 if (newOffset_ + ctrlData.diffLength > newSize_) { 78 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_); 79 return PATCH_INVALID_PATCH; 80 } 81 82 ret = RestoreDiffData(ctrlData); 83 if (ret != 0) { 84 PATCH_LOGE("Failed to read diff data"); 85 return ret; 86 } 87 oldOffset_ += ctrlData.diffLength; 88 newOffset_ += ctrlData.diffLength; 89 if (newOffset_ + ctrlData.extraLength > newSize_) { 90 PATCH_LOGE("Failed to check new offset %ld %zu", ctrlData.diffLength, newOffset_); 91 return PATCH_INVALID_PATCH; 92 } 93 94 ret = RestoreExtraData(ctrlData); 95 if (ret != 0) { 96 PATCH_LOGE("Failed to read extra data"); 97 return ret; 98 } 99 100 newOffset_ += ctrlData.extraLength; 101 oldOffset_ += ctrlData.offsetIncrement; 102 } 103 controlDataReader_->Close(); 104 diffDataReader_->Close(); 105 extraDataReader_->Close(); 106 return 0; 107} 108 109int32_t BlocksPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize) 110{ 111 if (patchInfo_.buffer == nullptr || patchInfo_.length < patchInfo_.start || 112 patchInfo_.length - patchInfo_.start <= PATCH_MIN) { 113 PATCH_LOGE("Invalid parm"); 114 return -1; 115 } 116 BlockBuffer patchData = {patchInfo_.buffer + patchInfo_.start, patchInfo_.length - patchInfo_.start}; 117 PATCH_DEBUG("Restore patch hash %zu %zu %s", 118 patchInfo_.length, patchInfo_.start, GeneraterBufferHash(patchData).c_str()); 119 uint8_t *header = patchInfo_.buffer + patchInfo_.start; 120 if (memcmp(header, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) != 0) { 121 PATCH_LOGE("Corrupt patch, patch head != BSDIFF40"); 122 return -1; 123 } 124 /* Read lengths from header */ 125 size_t offset = std::char_traits<char>::length(BSDIFF_MAGIC); 126 controlDataSize = ReadLE64(header + offset); 127 offset += sizeof(int64_t); 128 diffDataSize = ReadLE64(header + offset); 129 offset += sizeof(int64_t); 130 newSize = ReadLE64(header + offset); 131 offset += sizeof(int64_t); 132 if (controlDataSize < 0) { 133 PATCH_LOGE("Invalid control data size"); 134 return -1; 135 } 136 if (newSize < 0) { 137 PATCH_LOGE("Invalid new data size"); 138 return -1; 139 } 140 if (diffDataSize < 0 || (diffDataSize + controlDataSize) > static_cast<int64_t>(patchInfo_.length)) { 141 PATCH_LOGE("Invalid patch data size"); 142 return -1; 143 } 144 BlockBuffer patchBuffer = {header, patchInfo_.length - patchInfo_.start}; 145 controlDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(controlDataSize), patchBuffer)); 146 offset += static_cast<size_t>(controlDataSize); 147 diffDataReader_.reset(new BZip2BufferReadAdapter(offset, static_cast<size_t>(diffDataSize), patchBuffer)); 148 offset += static_cast<size_t>(diffDataSize); 149 extraDataReader_.reset(new BZip2BufferReadAdapter(offset, 150 patchInfo_.length - patchInfo_.start - offset, patchBuffer)); 151 if (controlDataReader_ == nullptr || diffDataReader_ == nullptr || extraDataReader_ == nullptr) { 152 PATCH_LOGE("Failed to create reader"); 153 return -1; 154 } 155 controlDataReader_->Open(); 156 diffDataReader_->Open(); 157 extraDataReader_->Open(); 158 return 0; 159} 160 161int32_t BlocksPatch::ReadControlData(ControlData &ctrlData) 162{ 163 std::vector<uint8_t> data(sizeof(int64_t), 0); 164 BlockBuffer info = {data.data(), sizeof(int64_t)}; 165 int32_t ret = controlDataReader_->ReadData(info); 166 if (ret != 0) { 167 PATCH_LOGE("Failed to read diffLength"); 168 return ret; 169 } 170 ctrlData.diffLength = ReadLE64(info.buffer); 171 ret = controlDataReader_->ReadData(info); 172 if (ret != 0) { 173 PATCH_LOGE("Failed to read extraLength"); 174 return ret; 175 } 176 ctrlData.extraLength = ReadLE64(info.buffer); 177 ret = controlDataReader_->ReadData(info); 178 if (ret != 0) { 179 PATCH_LOGE("Failed to read offsetIncrement"); 180 return ret; 181 } 182 ctrlData.offsetIncrement = ReadLE64(info.buffer); 183 return 0; 184} 185 186int32_t BlocksBufferPatch::ReadHeader(int64_t &controlDataSize, int64_t &diffDataSize, int64_t &newSize) 187{ 188 int32_t ret = BlocksPatch::ReadHeader(controlDataSize, diffDataSize, newSize); 189 if (ret != 0) { 190 PATCH_LOGE("Failed to read header"); 191 return -1; 192 } 193 PATCH_LOGI("ReadHeader controlDataSize: %ld %ld %ld", controlDataSize, diffDataSize, newSize); 194 newData_.resize(newSize); 195 return 0; 196} 197 198int32_t BlocksBufferPatch::RestoreDiffData(const ControlData &ctrlData) 199{ 200 if (ctrlData.diffLength <= 0) { 201 return 0; 202 } 203 BlockBuffer diffData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.diffLength)}; 204 int32_t ret = diffDataReader_->ReadData(diffData); 205 if (ret != 0) { 206 PATCH_LOGE("Failed to read diff data"); 207 return ret; 208 } 209 210 for (int64_t i = 0; i < ctrlData.diffLength; i++) { 211 if (((oldOffset_ + i) >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldInfo_.length)) { 212 newData_[newOffset_ + i] += oldInfo_.buffer[oldOffset_ + i]; 213 } 214 } 215 return 0; 216} 217 218int32_t BlocksBufferPatch::RestoreExtraData(const ControlData &ctrlData) 219{ 220 if (ctrlData.extraLength <= 0) { 221 return 0; 222 } 223 BlockBuffer extraData = {newData_.data() + newOffset_, static_cast<size_t>(ctrlData.extraLength)}; 224 int32_t ret = extraDataReader_->ReadData(extraData); 225 if (ret != 0) { 226 PATCH_LOGE("Failed to read extra data"); 227 return ret; 228 } 229 return 0; 230} 231 232int32_t BlocksStreamPatch::RestoreDiffData(const ControlData &ctrlData) 233{ 234 if (ctrlData.diffLength <= 0) { 235 return 0; 236 } 237 std::vector<uint8_t> diffData(ctrlData.diffLength); 238 BlockBuffer diffBuffer = {diffData.data(), diffData.size()}; 239 int32_t ret = diffDataReader_->ReadData(diffBuffer); 240 if (ret != 0) { 241 PATCH_LOGE("Failed to read diff data"); 242 return ret; 243 } 244 245 size_t oldOffset = static_cast<size_t>(oldOffset_); 246 size_t oldLength = stream_->GetFileLength(); 247 PkgBuffer buffer {}; 248 if (stream_->GetStreamType() == PkgStream::PkgStreamType_MemoryMap || 249 stream_->GetStreamType() == PkgStream::PkgStreamType_Buffer) { 250 ret = stream_->GetBuffer(buffer); 251 if (ret != 0) { 252 PATCH_LOGE("Failed to get old buffer"); 253 return ret; 254 } 255 } else { 256 std::vector<uint8_t> oldData(ctrlData.diffLength); 257 size_t readLen = 0; 258 ret = stream_->Read(buffer, oldOffset_, ctrlData.diffLength, readLen); 259 if (ret != 0 || readLen != static_cast<size_t>(ctrlData.diffLength)) { 260 PATCH_LOGE("Failed to get old buffer"); 261 return ret; 262 } 263 oldOffset = 0; 264 } 265 for (int64_t i = 0; i < ctrlData.diffLength; i++) { 266 if ((oldOffset_ + i >= 0) && (static_cast<size_t>(oldOffset_ + i) < oldLength)) { 267 diffData[i] += buffer.buffer[static_cast<int64_t>(oldOffset) + i]; 268 } 269 } 270 // write 271 return writer_->Write(newOffset_, diffBuffer, static_cast<size_t>(ctrlData.diffLength)); 272} 273 274int32_t BlocksStreamPatch::RestoreExtraData(const ControlData &ctrlData) 275{ 276 if (ctrlData.extraLength <= 0) { 277 return 0; 278 } 279 std::vector<uint8_t> extraData(ctrlData.extraLength); 280 BlockBuffer extraBuffer = {extraData.data(), static_cast<size_t>(ctrlData.extraLength)}; 281 int32_t ret = extraDataReader_->ReadData(extraBuffer); 282 if (ret != 0) { 283 PATCH_LOGE("Failed to read extra data"); 284 return ret; 285 } 286 // write 287 return writer_->Write(newOffset_, extraBuffer, static_cast<size_t>(ctrlData.extraLength)); 288} 289} // namespace UpdatePatch 290