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