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 <cerrno>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <memory>
20 #include "pkg_manager.h"
21 #include "pkg_manager_impl.h"
22 #include "pkg_utils.h"
23 #include "securec.h"
24
25 namespace hpackage {
GetFileName() const26 const std::string PkgStreamImpl::GetFileName() const
27 {
28 return fileName_;
29 }
30
ConvertPkgStream(PkgManager::StreamPtr stream)31 PkgStreamPtr PkgStreamImpl::ConvertPkgStream(PkgManager::StreamPtr stream)
32 {
33 return (PkgStreamPtr)stream;
34 }
35
AddRef()36 void PkgStreamImpl::AddRef()
37 {
38 refCount_++;
39 }
40
DelRef()41 void PkgStreamImpl::DelRef()
42 {
43 refCount_--;
44 }
45
IsRef() const46 bool PkgStreamImpl::IsRef() const
47 {
48 return refCount_ == 0;
49 }
50
PostDecodeProgress(int type,size_t writeDataLen,const void * context)51 void PkgStreamImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context)
52 {
53 if (pkgManager_ != nullptr) {
54 pkgManager_->PostDecodeProgress(type, writeDataLen, context);
55 }
56 }
57
~FileStream()58 FileStream::~FileStream()
59 {
60 if (stream_ != nullptr) {
61 fflush(stream_);
62 fclose(stream_);
63 stream_ = nullptr;
64 }
65 }
66
Read(const PkgBuffer & data,size_t offset,size_t needRead,size_t & readLen)67 int32_t FileStream::Read(const PkgBuffer &data, size_t offset, size_t needRead, size_t &readLen)
68 {
69 PKG_CHECK(stream_ != nullptr, return PKG_INVALID_STREAM, "Invalid stream");
70 PKG_CHECK(data.length >= needRead, return PKG_INVALID_STREAM, "Invalid stream");
71 readLen = 0;
72 size_t len = GetFileLength();
73 fseek(stream_, offset, SEEK_SET);
74 PKG_CHECK(offset <= len, return PKG_INVALID_STREAM, "Invalid offset");
75 len = fread(data.buffer, 1, needRead, stream_);
76 readLen = len;
77 return PKG_SUCCESS;
78 }
79
Write(const PkgBuffer & data,size_t size,size_t offset)80 int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t offset)
81 {
82 PKG_CHECK(streamType_ == PkgStreamType_Write, return PKG_INVALID_STREAM, "Invalid stream type");
83 PKG_CHECK(stream_ != nullptr, return PKG_INVALID_STREAM, "Invalid stream");
84 fseek(stream_, offset, SEEK_SET);
85 size_t len = fwrite(data.buffer, size, 1, stream_);
86 PKG_CHECK(len == 1, return PKG_INVALID_STREAM, "Write buffer fail");
87 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr);
88 return PKG_SUCCESS;
89 }
90
GetFileLength()91 size_t FileStream::GetFileLength()
92 {
93 PKG_CHECK(stream_ != nullptr, return 0, "Invalid stream");
94 if (fileLength_ == 0) {
95 PKG_CHECK(Seek(0, SEEK_END) == 0, return -1, "Invalid stream");
96 off_t pos = ftello(stream_);
97 if (pos < 0) {
98 PKG_LOGE("Failed to get file length, err = %d", errno);
99 return 0;
100 }
101 fileLength_ = static_cast<size_t>(pos);
102 fseek(stream_, 0, SEEK_SET);
103 }
104 return fileLength_;
105 }
106
Seek(long int offset,int whence)107 int32_t FileStream::Seek(long int offset, int whence)
108 {
109 PKG_CHECK(stream_ != nullptr, return PKG_INVALID_STREAM, "Invalid stream");
110 return fseek(stream_, offset, whence);
111 }
112
Flush(size_t size)113 int32_t FileStream::Flush(size_t size)
114 {
115 PKG_CHECK(stream_ != nullptr, return PKG_INVALID_STREAM, "Invalid stream");
116 if (fileLength_ == 0) {
117 fileLength_ = size;
118 }
119 PKG_CHECK(fflush(stream_) == 0, return PKG_INVALID_STREAM, "Invalid stream");
120 return PKG_SUCCESS;
121 }
122
~MemoryMapStream()123 MemoryMapStream::~MemoryMapStream()
124 {
125 PKG_CHECK(memMap_ != nullptr, return, "Invalid memory map");
126 if (streamType_ == PkgStreamType_MemoryMap) {
127 ReleaseMemory(memMap_, memSize_);
128 }
129 }
130
Read(const PkgBuffer & data,size_t start,size_t needRead,size_t & readLen)131 int32_t MemoryMapStream::Read(const PkgBuffer &data, size_t start, size_t needRead, size_t &readLen)
132 {
133 PKG_CHECK(memMap_ != nullptr, return PKG_INVALID_STREAM, "Invalid memory map");
134 PKG_CHECK(start <= memSize_, return PKG_INVALID_STREAM, "Invalid start");
135 PKG_CHECK(data.length >= needRead, return PKG_INVALID_STREAM, "Invalid start");
136
137 MemoryMapStream::Seek(start, SEEK_SET);
138 size_t copyLen = GetFileLength() - start;
139 readLen = ((copyLen > needRead) ? needRead : copyLen);
140 PKG_CHECK(!memcpy_s(data.buffer, needRead, memMap_ + currOffset_, readLen), return PKG_NONE_MEMORY,
141 "Memcpy failed size:%zu, start:%zu copyLen:%zu %zu", needRead, start, copyLen, readLen);
142 return PKG_SUCCESS;
143 }
144
Write(const PkgBuffer & data,size_t size,size_t start)145 int32_t MemoryMapStream::Write(const PkgBuffer &data, size_t size, size_t start)
146 {
147 PKG_CHECK(memMap_ != nullptr, return PKG_INVALID_STREAM, "Invalid memory map");
148 PKG_CHECK(start <= memSize_, return PKG_INVALID_STREAM, "Invalid start");
149
150 currOffset_ = start;
151 size_t copyLen = memSize_ - start;
152 PKG_CHECK(copyLen >= size, return PKG_INVALID_STREAM, "Write fail copyLen %zu, %zu", copyLen, size);
153 int32_t ret = memcpy_s(memMap_ + currOffset_, memSize_ - currOffset_, data.buffer, size);
154 PKG_CHECK(ret == PKG_SUCCESS, return PKG_INVALID_STREAM, "Write fail");
155 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr);
156 return PKG_SUCCESS;
157 }
158
Seek(long int offset,int whence)159 int32_t MemoryMapStream::Seek(long int offset, int whence)
160 {
161 if (whence == SEEK_SET) {
162 PKG_CHECK(offset >= 0, return PKG_INVALID_STREAM, "Invalid offset");
163 PKG_CHECK(static_cast<size_t>(offset) <= memSize_, return PKG_INVALID_STREAM, "Invalid offset");
164 currOffset_ = offset;
165 } else if (whence == SEEK_CUR) {
166 PKG_CHECK(static_cast<size_t>(offset) <= (memSize_ - currOffset_), return PKG_INVALID_STREAM,
167 "Invalid offset");
168 currOffset_ += offset;
169 } else {
170 PKG_CHECK(offset <= 0, return PKG_INVALID_STREAM, "Invalid offset");
171 PKG_CHECK((memSize_ + offset) <= memSize_, return PKG_INVALID_STREAM, "Invalid offset");
172 PKG_CHECK((memSize_ + offset) >= 0, return PKG_INVALID_STREAM, "Invalid offset");
173 currOffset_ = memSize_ + offset;
174 }
175 return PKG_SUCCESS;
176 }
177 } // namespace hpackage
178