1/* 2 * Copyright (c) 2024-2024 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 <cinttypes> 17#include <algorithm> 18#include <mutex> 19#include <stdexcept> 20#include <string> 21 22#include "random_access_file_input.h" 23 24namespace OHOS { 25namespace SignatureTools { 26RandomAccessFileInput::RandomAccessFileInput(RandomAccessFile& file) : file(file), 27 startIndex(0), size(-1) 28{ 29} 30 31RandomAccessFileInput::RandomAccessFileInput(RandomAccessFile& file, int64_t offset, int64_t size) 32 : file(file), startIndex(offset), size(size) 33{ 34 if (offset < 0) { 35 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64, offset); 36 return; 37 } 38 if (size < 0) { 39 SIGNATURE_TOOLS_LOGE("out of range: size %" PRId64, size); 40 return; 41 } 42} 43 44int64_t RandomAccessFileInput::Size() 45{ 46 if (size == -1) { 47 return file.GetLength(); 48 } 49 return size; 50} 51 52bool RandomAccessFileInput::CopyTo(int64_t offset, int size, ByteBuffer& buffer) 53{ 54 int64_t srcSize = Size(); 55 if (!CheckBoundValid(offset, size, srcSize)) { 56 return false; 57 } 58 if (size == 0) { 59 SIGNATURE_TOOLS_LOGE("Copy size is equal to 0"); 60 return false; 61 } 62 if (size > buffer.Remaining()) { 63 SIGNATURE_TOOLS_LOGE("The length size passed in is greater than the reserved length of ByteBuffer"); 64 return false; 65 } 66 int64_t offsetInFile = startIndex + offset; 67 int remaining = size; 68 int originalLimit = buffer.GetLimit(); 69 70 buffer.SetLimit(buffer.GetPosition() + size); 71 int64_t readSize; 72 while (remaining > 0) { 73 { 74 std::mutex tmpMutex; 75 std::scoped_lock lock(tmpMutex); 76 readSize = file.ReadFileFullyFromOffset(buffer, offsetInFile); 77 } 78 offsetInFile += readSize; 79 remaining -= readSize; 80 } 81 int cap = buffer.GetCapacity(); 82 buffer.SetPosition(cap); 83 buffer.SetLimit(originalLimit); 84 return true; 85} 86 87ByteBuffer RandomAccessFileInput::CreateByteBuffer(int64_t offset, int size) 88{ 89 ByteBuffer byteBuffer; 90 if (size < 0) { 91 SIGNATURE_TOOLS_LOGE("IndexOutOfBounds: The created ByteBuffer size %d is less than 0", size); 92 return byteBuffer; 93 } 94 95 byteBuffer.SetCapacity(size); 96 if (!CopyTo(offset, size, byteBuffer)) { 97 byteBuffer.SetCapacity(0); 98 return byteBuffer; 99 } 100 101 return byteBuffer.Flip(); 102} 103 104DataSource* RandomAccessFileInput::Slice(int64_t offset, int64_t size) 105{ 106 int64_t srcSize = Size(); 107 if (!CheckBoundValid(offset, size, srcSize)) { 108 return nullptr; 109 } 110 if (offset == 0 && size == srcSize) { 111 SIGNATURE_TOOLS_LOGI("offset: 0, size: %" PRId64 ", it will return itself", size); 112 return new FileDataSource(file, startIndex, size, 0); 113 } 114 return new FileDataSource(file, offset, size, 0); 115} 116 117bool RandomAccessFileInput::CheckBoundValid(int64_t offset, int64_t size, int64_t sourceSize) 118{ 119 if (offset < 0) { 120 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64, offset); 121 return false; 122 } 123 if (size < 0) { 124 SIGNATURE_TOOLS_LOGE("out of range: size %" PRId64, size); 125 return false; 126 } 127 if (offset > sourceSize) { 128 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " is greater than sourceSize %" PRId64, 129 offset, sourceSize); 130 return false; 131 } 132 int64_t endOffset = offset + size; 133 if (endOffset < offset) { 134 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " add size %" PRId64 " is overflow", 135 offset, size); 136 return false; 137 } 138 if (endOffset > sourceSize) { 139 SIGNATURE_TOOLS_LOGE("out of range: offset %" PRId64 " add size %" PRId64 " is greater than " 140 "sourceSize %" PRId64, offset, size, sourceSize); 141 return false; 142 } 143 return true; 144} 145} // namespace SignatureTools 146} // namespace OHOS