• 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 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