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 <cstdio>
17 #include "pkg_manager.h"
18 #include "pkg_utils.h"
19 #include "securec.h"
20
21 #ifdef __APPLE__
22 #define off64_t off_t
23 #define fopen64 fopen
24 #define ftello64 ftello
25 #define fseeko64 fseek
26 #endif
27
28 namespace Hpackage {
GetFileName() const29 const std::string PkgStreamImpl::GetFileName() const
30 {
31 return fileName_;
32 }
33
ConvertPkgStream(PkgManager::StreamPtr stream)34 PkgStreamPtr PkgStreamImpl::ConvertPkgStream(PkgManager::StreamPtr stream)
35 {
36 return (PkgStreamPtr)stream;
37 }
38
AddRef()39 void PkgStreamImpl::AddRef()
40 {
41 refCount_++;
42 }
43
DelRef()44 void PkgStreamImpl::DelRef()
45 {
46 refCount_--;
47 }
48
IsRef() const49 bool PkgStreamImpl::IsRef() const
50 {
51 return refCount_ == 0;
52 }
53
PostDecodeProgress(int type,size_t writeDataLen,const void * context) const54 void PkgStreamImpl::PostDecodeProgress(int type, size_t writeDataLen, const void *context) const
55 {
56 if (pkgManager_ != nullptr) {
57 pkgManager_->PostDecodeProgress(type, writeDataLen, context);
58 }
59 }
60
~FileStream()61 FileStream::~FileStream()
62 {
63 if (stream_ != nullptr) {
64 fflush(stream_);
65 fclose(stream_);
66 stream_ = nullptr;
67 }
68 }
69
Read(const PkgBuffer & data,size_t start,size_t needRead,size_t & readLen)70 int32_t FileStream::Read(const PkgBuffer &data, size_t start, size_t needRead, size_t &readLen)
71 {
72 if (stream_ == nullptr) {
73 PKG_LOGE("Invalid stream");
74 return PKG_INVALID_STREAM;
75 }
76 if (data.length < needRead) {
77 PKG_LOGE("Invalid stream");
78 return PKG_INVALID_STREAM;
79 }
80 readLen = 0;
81 if (fseeko64(stream_, start, SEEK_SET) != 0) {
82 PKG_LOGE("read data fail");
83 return PKG_INVALID_STREAM;
84 }
85 if (start > GetFileLength()) {
86 PKG_LOGE("Invalid start");
87 return PKG_INVALID_STREAM;
88 }
89 readLen = fread(data.buffer, 1, needRead, stream_);
90 if (readLen == 0) {
91 PKG_LOGE("read data fail");
92 return PKG_INVALID_STREAM;
93 }
94 return PKG_SUCCESS;
95 }
96
Write(const PkgBuffer & data,size_t size,size_t start)97 int32_t FileStream::Write(const PkgBuffer &data, size_t size, size_t start)
98 {
99 if (streamType_ != PkgStreamType_Write) {
100 PKG_LOGE("Invalid stream type");
101 return PKG_INVALID_STREAM;
102 }
103 if (stream_ == nullptr) {
104 PKG_LOGE("Invalid stream");
105 return PKG_INVALID_STREAM;
106 }
107 if (fseeko64(stream_, start, SEEK_SET) != 0) {
108 PKG_LOGE("write data fail");
109 return PKG_INVALID_STREAM;
110 }
111 size_t len = fwrite(data.buffer, size, 1, stream_);
112 if (len != 1) {
113 PKG_LOGE("Write buffer fail");
114 return PKG_INVALID_STREAM;
115 }
116 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr);
117 return PKG_SUCCESS;
118 }
119
GetFileLength()120 size_t FileStream::GetFileLength()
121 {
122 if (stream_ == nullptr) {
123 PKG_LOGE("Invalid stream");
124 return 0;
125 }
126 if (fileLength_ == 0) {
127 if (Seek(0, SEEK_END) != 0) {
128 PKG_LOGE("Invalid stream");
129 return -1;
130 }
131 off64_t ret = ftello64(stream_);
132 if (ret < 0) {
133 PKG_LOGE("ftell64 failed");
134 return PKG_INVALID_STREAM;
135 }
136 fileLength_ = static_cast<size_t>(ret);
137 if (fseek(stream_, 0, SEEK_SET) != 0) {
138 PKG_LOGE("fseek failed");
139 return PKG_INVALID_STREAM;
140 }
141 }
142 return fileLength_;
143 }
144
Seek(long int offset,int whence)145 int32_t FileStream::Seek(long int offset, int whence)
146 {
147 if (stream_ == nullptr) {
148 PKG_LOGE("Invalid stream");
149 return PKG_INVALID_STREAM;
150 }
151 return fseek(stream_, offset, whence);
152 }
153
Flush(size_t size)154 int32_t FileStream::Flush(size_t size)
155 {
156 if (stream_ == nullptr) {
157 PKG_LOGE("Invalid stream");
158 return PKG_INVALID_STREAM;
159 }
160 if (fileLength_ == 0) {
161 fileLength_ = size;
162 }
163 if (fseek(stream_, 0, SEEK_END) != 0) {
164 PKG_LOGE("fseek failed");
165 return PKG_INVALID_STREAM;
166 }
167 off64_t ret = ftello64(stream_);
168 if (ret < 0) {
169 PKG_LOGE("ftell64 failed");
170 return PKG_INVALID_STREAM;
171 }
172 fileLength_ = static_cast<size_t>(ret);
173 if (size != fileLength_) {
174 PKG_LOGE("Flush size %zu local size:%zu", size, fileLength_);
175 }
176 if (fflush(stream_) != 0) {
177 PKG_LOGE("Invalid stream");
178 return PKG_INVALID_STREAM;
179 }
180 return PKG_SUCCESS;
181 }
182
~MemoryMapStream()183 MemoryMapStream::~MemoryMapStream()
184 {
185 if (memMap_ == nullptr) {
186 PKG_LOGE("Invalid memory map");
187 return;
188 }
189 if (streamType_ == PkgStreamType_MemoryMap) {
190 ReleaseMemory(memMap_, memSize_);
191 }
192 }
193
Read(const PkgBuffer & data,size_t start,size_t needRead,size_t & readLen)194 int32_t MemoryMapStream::Read(const PkgBuffer &data, size_t start, size_t needRead, size_t &readLen)
195 {
196 if (memMap_ == nullptr) {
197 PKG_LOGE("Invalid memory map");
198 return PKG_INVALID_STREAM;
199 }
200 if (start > memSize_) {
201 PKG_LOGE("Invalid start");
202 return PKG_INVALID_STREAM;
203 }
204 if (data.length < needRead) {
205 PKG_LOGE("Invalid start");
206 return PKG_INVALID_STREAM;
207 }
208
209 MemoryMapStream::Seek(start, SEEK_SET);
210 size_t copyLen = GetFileLength() - start;
211 readLen = ((copyLen > needRead) ? needRead : copyLen);
212 if (memcpy_s(data.buffer, needRead, memMap_ + currOffset_, readLen) != EOK) {
213 PKG_LOGE("Memcpy failed size:%zu, start:%zu copyLen:%zu %zu", needRead, start, copyLen, readLen);
214 return PKG_NONE_MEMORY;
215 }
216 return PKG_SUCCESS;
217 }
218
Write(const PkgBuffer & data,size_t size,size_t start)219 int32_t MemoryMapStream::Write(const PkgBuffer &data, size_t size, size_t start)
220 {
221 if (memMap_ == nullptr) {
222 PKG_LOGE("Invalid memory map");
223 return PKG_INVALID_STREAM;
224 }
225 if (start > memSize_) {
226 PKG_LOGE("Invalid start");
227 return PKG_INVALID_STREAM;
228 }
229
230 currOffset_ = start;
231 size_t copyLen = memSize_ - start;
232 if (copyLen < size) {
233 PKG_LOGE("Write fail copyLen %zu, %zu", copyLen, size);
234 return PKG_INVALID_STREAM;
235 }
236 int32_t ret = memcpy_s(memMap_ + currOffset_, memSize_ - currOffset_, data.buffer, size);
237 if (ret != PKG_SUCCESS) {
238 PKG_LOGE("Write fail");
239 return PKG_INVALID_STREAM;
240 }
241 PostDecodeProgress(POST_TYPE_DECODE_PKG, size, nullptr);
242 return PKG_SUCCESS;
243 }
244
Seek(long int offset,int whence)245 int32_t MemoryMapStream::Seek(long int offset, int whence)
246 {
247 if (whence == SEEK_SET) {
248 if (offset < 0) {
249 PKG_LOGE("Invalid offset");
250 return PKG_INVALID_STREAM;
251 }
252 if (static_cast<size_t>(offset) > memSize_) {
253 PKG_LOGE("Invalid offset");
254 return PKG_INVALID_STREAM;
255 }
256 currOffset_ = static_cast<size_t>(offset);
257 } else if (whence == SEEK_CUR) {
258 if (static_cast<size_t>(offset) > (memSize_ - currOffset_)) {
259 PKG_LOGE("Invalid offset");
260 return PKG_INVALID_STREAM;
261 }
262 currOffset_ += static_cast<size_t>(offset);
263 } else {
264 if (offset > 0) {
265 PKG_LOGE("Invalid offset");
266 return PKG_INVALID_STREAM;
267 }
268 auto memSize = static_cast<long long>(memSize_);
269 if (memSize + offset < 0) {
270 PKG_LOGE("Invalid offset");
271 return PKG_INVALID_STREAM;
272 }
273 currOffset_ = static_cast<size_t>(memSize + offset);
274 }
275 return PKG_SUCCESS;
276 }
277 } // namespace Hpackage
278