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
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 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
Write(const PkgBuffer & data,size_t size,size_t start)112 int32_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
GetFileLength()135 size_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 -1;
145 }
146 off64_t ret = ftello64(stream_);
147 if (ret < 0) {
148 PKG_LOGE("ftell64 failed");
149 return PKG_INVALID_STREAM;
150 }
151 fileLength_ = static_cast<size_t>(ret);
152 if (fseek(stream_, 0, SEEK_SET) != 0) {
153 PKG_LOGE("fseek failed");
154 return PKG_INVALID_STREAM;
155 }
156 }
157 return fileLength_;
158 }
159
Seek(long int offset,int whence)160 int32_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
Flush(size_t size)169 int32_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
~MemoryMapStream()198 MemoryMapStream::~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
Read(PkgBuffer & data,size_t start,size_t needRead,size_t & readLen)209 int32_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
Write(const PkgBuffer & data,size_t size,size_t start)236 int32_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
Seek(long int offset,int whence)262 int32_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
Read(PkgBuffer & data,size_t start,size_t needRead,size_t & readLen)295 int32_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
ReadFromRingBuf(uint8_t * & buff,const uint32_t needLen,uint32_t & readLen)334 int32_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
Write(const PkgBuffer & data,size_t size,size_t start)356 int32_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 } // namespace Hpackage
376