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