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