• 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 
16 #include <unistd.h>
17 #include "image_log.h"
18 #include "image_utils.h"
19 #include "media_errors.h"
20 #include "directory_ex.h"
21 #include "file_packer_stream.h"
22 #include "file_source_stream.h"
23 
24 #if !defined(_WIN32) && !defined(_APPLE) &&!defined(IOS_PLATFORM) &&!defined(A_PLATFORM)
25 #include <sys/mman.h>
26 #define SUPPORT_MMAP
27 #endif
28 
29 namespace OHOS {
30 namespace Media {
31 using namespace OHOS::HiviewDFX;
32 using namespace std;
33 using namespace ImagePlugin;
34 
FileSourceStream(std::FILE * file,size_t size,size_t offset,size_t original)35 FileSourceStream::FileSourceStream(std::FILE *file, size_t size, size_t offset, size_t original)
36     : filePtr_(file), fileSize_(size), fileOffset_(offset), fileOriginalOffset_(original)
37 {}
38 
~FileSourceStream()39 FileSourceStream::~FileSourceStream()
40 {
41     IMAGE_LOGE("[FileSourceStream]destructor enter.");
42     fclose(filePtr_);
43     ResetReadBuffer();
44 }
45 
CreateSourceStream(const string & pathName)46 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const string &pathName)
47 {
48     string realPath;
49     if (!PathToRealPath(pathName, realPath)) {
50         IMAGE_LOGE("[FileSourceStream]input the file path exception.");
51         return nullptr;
52     }
53     size_t size = 0;
54     if (!ImageUtils::GetFileSize(realPath, size)) {
55         IMAGE_LOGE("[FileSourceStream]get the file size fail.");
56         return nullptr;
57     }
58     FILE *filePtr = fopen(realPath.c_str(), "rb");
59     if (filePtr == nullptr) {
60         IMAGE_LOGE("[FileSourceStream]open file fail.");
61         return nullptr;
62     }
63     int64_t offset = ftell(filePtr);
64     if (offset < 0) {
65         IMAGE_LOGE("[FileSourceStream]get the position fail.");
66         fclose(filePtr);
67         return nullptr;
68     }
69     return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
70 }
71 
CreateSourceStream(const int fd)72 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const int fd)
73 {
74     size_t size = 0;
75 
76     int dupFd = dup(fd);
77     if (dupFd < 0) {
78         IMAGE_LOGE("[FileSourceStream]Fail to dup fd.");
79         return nullptr;
80     }
81 
82     if (!ImageUtils::GetFileSize(dupFd, size)) {
83         IMAGE_LOGE("[FileSourceStream]get the file size fail.");
84         return nullptr;
85     }
86     FILE *filePtr = fdopen(dupFd, "rb");
87     if (filePtr == nullptr) {
88         IMAGE_LOGE("[FileSourceStream]open file fail.");
89         return nullptr;
90     }
91 
92     int ret = fseek(filePtr, 0, SEEK_SET);
93     if (ret != 0) {
94         IMAGE_LOGE("[FileSourceStream]Go to 0 position fail, ret:%{public}d.", ret);
95     }
96 
97     int64_t offset = ftell(filePtr);
98     if (offset < 0) {
99         IMAGE_LOGE("[FileSourceStream]get the position fail.");
100         fclose(filePtr);
101         return nullptr;
102     }
103     return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
104 }
105 
Read(uint32_t desiredSize,DataStreamBuffer & outData)106 bool FileSourceStream::Read(uint32_t desiredSize, DataStreamBuffer &outData)
107 {
108     if (desiredSize == 0 || filePtr_ == nullptr) {
109         IMAGE_LOGE("[FileSourceStream]read stream input parameter exception.");
110         return false;
111     }
112     if (!GetData(desiredSize, outData)) {
113         IMAGE_LOGE("[FileSourceStream]read fail.");
114         return false;
115     }
116     fileOffset_ += outData.dataSize;
117     return true;
118 }
119 
Peek(uint32_t desiredSize,DataStreamBuffer & outData)120 bool FileSourceStream::Peek(uint32_t desiredSize, DataStreamBuffer &outData)
121 {
122     if (desiredSize == 0 || filePtr_ == nullptr) {
123         IMAGE_LOGE("[FileSourceStream]peek stream input parameter exception.");
124         return false;
125     }
126     if (!GetData(desiredSize, outData)) {
127         IMAGE_LOGE("[FileSourceStream]peek fail.");
128         return false;
129     }
130     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
131     if (ret != 0) {
132         IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
133         return false;
134     }
135     return true;
136 }
137 
Read(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)138 bool FileSourceStream::Read(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
139 {
140     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
141         IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
142                    fileSize_:%{public}zu.",
143                    desiredSize, bufferSize, fileSize_);
144         return false;
145     }
146     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
147         IMAGE_LOGE("[FileSourceStream]read fail.");
148         return false;
149     }
150     fileOffset_ += readSize;
151     return true;
152 }
153 
Peek(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)154 bool FileSourceStream::Peek(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
155 {
156     if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
157         IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
158                    fileSize_:%{public}zu.",
159                    desiredSize, bufferSize, fileSize_);
160         return false;
161     }
162     if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
163         IMAGE_LOGE("[FileSourceStream]peek fail.");
164         return false;
165     }
166     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
167     if (ret != 0) {
168         IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
169         return false;
170     }
171     return true;
172 }
173 
Seek(uint32_t position)174 bool FileSourceStream::Seek(uint32_t position)
175 {
176     if (position > fileSize_) {
177         IMAGE_LOGE("[FileSourceStream]Seek the position greater than the file size, position:%{public}u.", position);
178         return false;
179     }
180     size_t targetPosition = position + fileOriginalOffset_;
181     fileOffset_ = ((targetPosition < fileSize_) ? targetPosition : fileSize_);
182     int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
183     if (ret != 0) {
184         IMAGE_LOGE("[FileSourceStream]go to offset position fail, ret:%{public}d.", ret);
185         return false;
186     }
187     return true;
188 }
189 
Tell()190 uint32_t FileSourceStream::Tell()
191 {
192     return fileOffset_;
193 }
194 
GetData(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)195 bool FileSourceStream::GetData(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
196 {
197     if (fileSize_ == fileOffset_) {
198         IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
199         return false;
200     }
201     if (desiredSize > (fileSize_ - fileOffset_)) {
202         desiredSize = fileSize_ - fileOffset_;
203     }
204     size_t bytesRead = fread(outBuffer, sizeof(outBuffer[0]), desiredSize, filePtr_);
205     if (bytesRead < desiredSize) {
206         IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
207         return false;
208     }
209     readSize = desiredSize;
210     return true;
211 }
212 
GetData(uint32_t desiredSize,DataStreamBuffer & outData)213 bool FileSourceStream::GetData(uint32_t desiredSize, DataStreamBuffer &outData)
214 {
215     if (fileSize_ == fileOffset_) {
216         IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
217         return false;
218     }
219 
220     if (desiredSize == 0 || desiredSize > MALLOC_MAX_LENTH) {
221         IMAGE_LOGE("[FileSourceStream]Invalid value, desiredSize out of size.");
222         return false;
223     }
224 
225     ResetReadBuffer();
226     readBuffer_ = static_cast<uint8_t *>(malloc(desiredSize));
227     if (readBuffer_ == nullptr) {
228         IMAGE_LOGE("[FileSourceStream]malloc the desiredSize fail.");
229         return false;
230     }
231     outData.bufferSize = desiredSize;
232     if (desiredSize > (fileSize_ - fileOffset_)) {
233         desiredSize = fileSize_ - fileOffset_;
234     }
235     size_t bytesRead = fread(readBuffer_, sizeof(uint8_t), desiredSize, filePtr_);
236     if (bytesRead < desiredSize) {
237         IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
238         free(readBuffer_);
239         readBuffer_ = nullptr;
240         return false;
241     }
242     outData.inputStreamBuffer = static_cast<uint8_t *>(readBuffer_);
243     outData.dataSize = desiredSize;
244     return true;
245 }
246 
GetStreamSize()247 size_t FileSourceStream::GetStreamSize()
248 {
249     return fileSize_;
250 }
251 
DupFd(FILE * f,int & res)252 static bool DupFd(FILE *f, int &res)
253 {
254     res = fileno(f);
255     if (res < 0) {
256         IMAGE_LOGE("[FileSourceStream]Fail to fileno fd.");
257         return false;
258     }
259     res = dup(res);
260     if (res < 0) {
261         IMAGE_LOGE("[FileSourceStream]Fail to dup fd.");
262         return false;
263     }
264     return true;
265 }
266 
GetDataPtr()267 uint8_t *FileSourceStream::GetDataPtr()
268 {
269     if (fileData_ != nullptr) {
270         return fileData_;
271     }
272 #ifdef SUPPORT_MMAP
273     int dupFd = -1;
274     if (!DupFd(filePtr_, dupFd)) {
275         return nullptr;
276     }
277     auto mmptr = ::mmap(nullptr, fileSize_, PROT_READ, MAP_SHARED, dupFd, 0);
278     if (mmptr == MAP_FAILED) {
279         HiLog::Error(LABEL, "[FileSourceStream] mmap failed, errno:%{public}d", errno);
280         return nullptr;
281     }
282     fileData_ = static_cast<uint8_t*>(mmptr);
283 #endif
284     return fileData_;
285 }
286 
GetStreamType()287 uint32_t FileSourceStream::GetStreamType()
288 {
289     return ImagePlugin::FILE_STREAM_TYPE;
290 }
291 
ResetReadBuffer()292 void FileSourceStream::ResetReadBuffer()
293 {
294     if (readBuffer_ != nullptr) {
295         free(readBuffer_);
296         readBuffer_ = nullptr;
297     }
298     if (fileData_ != nullptr) {
299 #ifdef SUPPORT_MMAP
300         ::munmap(fileData_, fileSize_);
301         fileData_ = nullptr;
302 #endif
303     }
304 }
305 
ToOutputDataStream()306 OutputDataStream* FileSourceStream::ToOutputDataStream()
307 {
308     int dupFd = -1;
309     if (DupFd(filePtr_, dupFd)) {
310         HiLog::Error(LABEL, "[FileSourceStream] ToOutputDataStream fd failed");
311         return nullptr;
312     }
313     return new (std::nothrow) FilePackerStream(dupFd);
314 }
315 } // namespace Media
316 } // namespace OHOS
317