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