• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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