* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "applypatch/block_writer.h"
#include <sys/types.h>
#include "applypatch/block_set.h"
#include "log/log.h"
#include "utils.h"
namespace Updater {
bool BlockWriter::IsWriteDone() const
{
return blockIndex_ == bs_.CountOfRanges() && currentBlockLeft_ == 0;
}
size_t BlockWriter::GetBlocksSize() const
{
return bs_.TotalBlockSize() * H_BLOCK_SIZE;
}
size_t BlockWriter::GetTotalWritten() const
{
return totalWritten_;
}
bool BlockWriter::Write(const uint8_t *addr, size_t len, [[maybe_unused]] const void *context)
{
if (IsWriteDone()) {
LOG(WARNING) << "BlockWriter: call writer while no more blocks need to write. skip " << len << " byte(s)";
return false;
}
if (offset_ < 0) {
LOG(ERROR) << "BlockWriter: offset " << offset_ << " is invalid";
return false;
}
while (len > 0) {
if (currentBlockLeft_ == 0) {
if (blockIndex_ >= bs_.CountOfRanges()) {
LOG(DEBUG) << "block write overflow";
return false;
}
const BlockPair &bp = bs_[blockIndex_];
off_t offset = static_cast<off_t>(bp.first) * H_BLOCK_SIZE + static_cast<off_t>(offset_);
currentBlockLeft_ = (bp.second - bp.first) * H_BLOCK_SIZE;
blockIndex_++;
if (lseek(fd_, offset, SEEK_SET) < 0) {
LOG(ERROR) << "BlockWriter: Cannot seek to offset: " << offset << " Block index: " << blockIndex_;
return false;
}
}
size_t written = len;
if (currentBlockLeft_ < len) {
written = currentBlockLeft_;
}
if (Updater::Utils::WriteFully(fd_, addr, written) == false) {
LOG(ERROR) << "BlockWriter: failed to write " << written << " byte(s).";
return false;
}
len -= written;
addr += written;
currentBlockLeft_ -= written;
totalWritten_ += written;
}
return true;
}
}