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 "pkg_stream.h" 16#include <fcntl.h> 17#include <sys/types.h> 18#include <sys/stat.h> 19#include <unistd.h> 20#include <cstdio> 21#include "dump.h" 22#include "pkg_manager.h" 23#include "pkg_utils.h" 24#include "securec.h" 25 26#ifdef __APPLE__ 27#define off64_t off_t 28#define fopen64 fopen 29#define ftello64 ftello 30#define fseeko64 fseek 31#endif 32 33namespace Hpackage { 34const std::string PkgStreamImpl::GetFileName() const 35{ 36 return fileName_; 37} 38 39PkgStreamPtr PkgStreamImpl::ConvertPkgStream(PkgManager::StreamPtr stream) 40{ 41 return (PkgStreamPtr)stream; 42} 43 44void PkgStreamImpl::AddRef() 45{ 46 refCount_++; 47} 48 49void PkgStreamImpl::DelRef() 50{ 51 refCount_--; 52} 53 54bool PkgStreamImpl::IsRef() const 55{ 56 return refCount_ == 0; 57} 58 59void PkgStreamImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) const 60{ 61 if (pkgManager_ != nullptr) { 62 pkgManager_->PostDecodeProgress(type, writeDataLen, context); 63 } 64} 65 66FileStream::~FileStream() 67{ 68 if (stream_ != nullptr) { 69 fflush(stream_); 70 fclose(stream_); 71 stream_ = nullptr; 72 } 73} 74 75int32_t FileStream::Read(PkgBuffer &data, size_t start, size_t needRead, size_t &readLen) 76{ 77 Updater::UPDATER_INIT_RECORD; 78 if (stream_ == nullptr) { 79 PKG_LOGE("Invalid stream"); 80 UPDATER_LAST_WORD(PKG_INVALID_STREAM); 81 return PKG_INVALID_STREAM; 82 } 83 if (data.length < needRead) { 84 PKG_LOGE("insufficient buffer capacity"); 85 UPDATER_LAST_WORD(PKG_INVALID_STREAM); 86 return PKG_INVALID_STREAM; 87 } 88 readLen = 0; 89 if (fseeko64(stream_, start, SEEK_SET) != 0) { 90 PKG_LOGE("read data fail"); 91 UPDATER_LAST_WORD(PKG_INVALID_STREAM); 92 return PKG_INVALID_STREAM; 93 } 94 if (start > GetFileLength()) { 95 PKG_LOGE("Invalid start"); 96 UPDATER_LAST_WORD(PKG_INVALID_STREAM); 97 return PKG_INVALID_STREAM; 98 } 99 if (data.buffer == nullptr) { 100 data.data.resize(data.length); 101 data.buffer = data.data.data(); 102 } 103 readLen = fread(data.buffer, 1, needRead, stream_); 104 if (readLen == 0) { 105 PKG_LOGE("read data fail"); 106 UPDATER_LAST_WORD(PKG_INVALID_STREAM); 107 return PKG_INVALID_STREAM; 108 } 109 return PKG_SUCCESS; 110} 111 112int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t start) 113{ 114 if (streamType_ != PkgStreamType_Write) { 115 PKG_LOGE("Invalid stream type"); 116 return PKG_INVALID_STREAM; 117 } 118 if (stream_ == nullptr) { 119 PKG_LOGE("Invalid stream"); 120 return PKG_INVALID_STREAM; 121 } 122 if (fseeko64(stream_, start, SEEK_SET) != 0) { 123 PKG_LOGE("write data fail"); 124 return PKG_INVALID_STREAM; 125 } 126 size_t len = fwrite(data.buffer, size, 1, stream_); 127 if (len != 1) { 128 PKG_LOGE("Write buffer fail"); 129 return PKG_INVALID_STREAM; 130 } 131 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); 132 return PKG_SUCCESS; 133} 134 135size_t FileStream::GetFileLength() 136{ 137 if (stream_ == nullptr) { 138 PKG_LOGE("Invalid stream"); 139 return 0; 140 } 141 if (fileLength_ == 0) { 142 if (Seek(0, SEEK_END) != 0) { 143 PKG_LOGE("Invalid stream"); 144 return 0; 145 } 146 off64_t ret = ftello64(stream_); 147 if (ret < 0) { 148 PKG_LOGE("ftell64 failed"); 149 return 0; 150 } 151 fileLength_ = static_cast<size_t>(ret); 152 if (fseek(stream_, 0, SEEK_SET) != 0) { 153 PKG_LOGE("fseek failed"); 154 return 0; 155 } 156 } 157 return fileLength_; 158} 159 160int32_t FileStream::Seek(long int offset, int whence) 161{ 162 if (stream_ == nullptr) { 163 PKG_LOGE("Invalid stream"); 164 return PKG_INVALID_STREAM; 165 } 166 return fseek(stream_, offset, whence); 167} 168 169int32_t FileStream::Flush(size_t size) 170{ 171 if (stream_ == nullptr) { 172 PKG_LOGE("Invalid stream"); 173 return PKG_INVALID_STREAM; 174 } 175 if (fileLength_ == 0) { 176 fileLength_ = size; 177 } 178 if (fseek(stream_, 0, SEEK_END) != 0) { 179 PKG_LOGE("fseek failed"); 180 return PKG_INVALID_STREAM; 181 } 182 off64_t ret = ftello64(stream_); 183 if (ret < 0) { 184 PKG_LOGE("ftell64 failed"); 185 return PKG_INVALID_STREAM; 186 } 187 fileLength_ = static_cast<size_t>(ret); 188 if (size != fileLength_) { 189 PKG_LOGE("Flush size %zu local size:%zu", size, fileLength_); 190 } 191 if (fflush(stream_) != 0) { 192 PKG_LOGE("Invalid stream"); 193 return PKG_INVALID_STREAM; 194 } 195 return PKG_SUCCESS; 196} 197 198MemoryMapStream::~MemoryMapStream() 199{ 200 if (memMap_ == nullptr) { 201 PKG_LOGE("Invalid memory map"); 202 return; 203 } 204 if (streamType_ == PkgStreamType_MemoryMap) { 205 ReleaseMemory(memMap_, memSize_); 206 } 207} 208 209int32_t MemoryMapStream::Read(PkgBuffer &data, size_t start, size_t needRead, size_t &readLen) 210{ 211 if (memMap_ == nullptr) { 212 PKG_LOGE("Invalid memory map"); 213 return PKG_INVALID_STREAM; 214 } 215 if (start > memSize_) { 216 PKG_LOGE("Invalid start"); 217 return PKG_INVALID_STREAM; 218 } 219 if (data.length < needRead) { 220 PKG_LOGE("insufficient buffer capacity"); 221 return PKG_INVALID_STREAM; 222 } 223 size_t copyLen = GetFileLength() - start; 224 readLen = ((copyLen > needRead) ? needRead : copyLen); 225 if (data.data.size() == 0) { 226 data.buffer = memMap_ + start; 227 } else { 228 if (memcpy_s(data.buffer, needRead, memMap_ + start, readLen) != EOK) { 229 PKG_LOGE("Memcpy failed size:%zu, start:%zu copyLen:%zu %zu", needRead, start, copyLen, readLen); 230 return PKG_NONE_MEMORY; 231 } 232 } 233 return PKG_SUCCESS; 234} 235 236int32_t MemoryMapStream::Write(const PkgBuffer &data, size_t size, size_t start) 237{ 238 if (memMap_ == nullptr) { 239 PKG_LOGE("Invalid memory map"); 240 return PKG_INVALID_STREAM; 241 } 242 if (start > memSize_) { 243 PKG_LOGE("Invalid start"); 244 return PKG_INVALID_STREAM; 245 } 246 247 currOffset_ = start; 248 size_t copyLen = memSize_ - start; 249 if (copyLen < size) { 250 PKG_LOGE("Write fail copyLen %zu, %zu", copyLen, size); 251 return PKG_INVALID_STREAM; 252 } 253 int32_t ret = memcpy_s(memMap_ + currOffset_, memSize_ - currOffset_, data.buffer, size); 254 if (ret != PKG_SUCCESS) { 255 PKG_LOGE("Write fail"); 256 return PKG_INVALID_STREAM; 257 } 258 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr); 259 return PKG_SUCCESS; 260} 261 262int32_t MemoryMapStream::Seek(long int offset, int whence) 263{ 264 if (whence == SEEK_SET) { 265 if (offset < 0) { 266 PKG_LOGE("Invalid offset"); 267 return PKG_INVALID_STREAM; 268 } 269 if (static_cast<size_t>(offset) > memSize_) { 270 PKG_LOGE("Invalid offset"); 271 return PKG_INVALID_STREAM; 272 } 273 currOffset_ = static_cast<size_t>(offset); 274 } else if (whence == SEEK_CUR) { 275 if (static_cast<size_t>(offset) > (memSize_ - currOffset_)) { 276 PKG_LOGE("Invalid offset"); 277 return PKG_INVALID_STREAM; 278 } 279 currOffset_ += static_cast<size_t>(offset); 280 } else { 281 if (offset > 0) { 282 PKG_LOGE("Invalid offset"); 283 return PKG_INVALID_STREAM; 284 } 285 auto memSize = static_cast<long long>(memSize_); 286 if (memSize + offset < 0) { 287 PKG_LOGE("Invalid offset"); 288 return PKG_INVALID_STREAM; 289 } 290 currOffset_ = static_cast<size_t>(memSize + offset); 291 } 292 return PKG_SUCCESS; 293} 294 295int32_t FlowDataStream::Read(PkgBuffer &data, size_t start, size_t needRead, size_t &readLen) 296{ 297 if (readOffset_ != start) { 298 PKG_LOGE("Invalid start, readOffset_: %d, start: %d", readOffset_, start); 299 return PKG_INVALID_STREAM; 300 } 301 302 if (data.length < needRead) { 303 PKG_LOGE("Invalid need length"); 304 return PKG_INVALID_STREAM; 305 } 306 307 if (data.buffer == nullptr) { 308 data.data.resize(needRead); 309 data.buffer = data.data.data(); 310 } 311 312 readLen = 0; 313 uint8_t *buffer = nullptr; 314 while (needRead - readLen > 0) { 315 uint32_t readOnce = 0; 316 if (ReadFromRingBuf(buffer, needRead - readLen, readOnce) != PKG_SUCCESS) { 317 PKG_LOGE("Fail to read header"); 318 return PKG_INVALID_STREAM; 319 } 320 if (buffer == nullptr || readOnce == 0) { 321 PKG_LOGE("Fail to read header, readOnce: %d", readOnce); 322 return PKG_INVALID_STREAM; 323 } 324 if (memcpy_s(data.buffer + readLen, readOnce, buffer, readOnce) != EOK) { 325 PKG_LOGE("Memcpy failed size:%zu, copyLen:%zu", needRead, readOnce); 326 return PKG_NONE_MEMORY; 327 } 328 readLen += readOnce; 329 } 330 readOffset_ += needRead; 331 return PKG_SUCCESS; 332} 333 334int32_t FlowDataStream::ReadFromRingBuf(uint8_t *&buff, const uint32_t needLen, uint32_t &readLen) 335{ 336 if (ringBuf_ == nullptr) { 337 PKG_LOGE("ringBuf_ is nullptr"); 338 buff = nullptr; 339 return PKG_INVALID_STREAM; 340 } 341 342 // buf_ is empty, read from ringbuf 343 if ((avail_ == 0) && !ringBuf_->Pop(buff_, MAX_FLOW_BUFFER_SIZE, avail_)) { 344 PKG_LOGE("read data fail"); 345 buff = nullptr; 346 return PKG_INVALID_STREAM; 347 } 348 349 buff = buff_ + bufOffset_; 350 readLen = needLen <= avail_ ? needLen : avail_; 351 avail_ -= readLen; 352 bufOffset_ = avail_ == 0 ? 0 : bufOffset_ + readLen; 353 return PKG_SUCCESS; 354} 355 356int32_t FlowDataStream::Write(const PkgBuffer &data, size_t size, size_t start) 357{ 358 if (ringBuf_ == nullptr) { 359 PKG_LOGE("ringBuf_ is nullptr"); 360 return PKG_INVALID_STREAM; 361 } 362 363 if (writeOffset_ != start) { 364 PKG_LOGE("Invalid start, writeOffset: %zu, start: %zu", writeOffset_, start); 365 return PKG_INVALID_STREAM; 366 } 367 368 if (ringBuf_->Push(data.buffer, size)) { 369 writeOffset_ += size; 370 return PKG_SUCCESS; 371 } 372 PKG_LOGE("Write ring buffer fail"); 373 return PKG_INVALID_STREAM; 374} 375 376void FlowDataStream::Stop() 377{ 378 PKG_LOGI("FlowDataStream stop"); 379 if (ringBuf_ != nullptr) { 380 ringBuf_->Stop(); 381 } 382} 383} // namespace Hpackage 384