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_source_stream.h"
22
23 namespace OHOS {
24 namespace Media {
25 using namespace OHOS::HiviewDFX;
26 using namespace std;
27 using namespace ImagePlugin;
28
FileSourceStream(std::FILE * file,size_t size,size_t offset,size_t original)29 FileSourceStream::FileSourceStream(std::FILE *file, size_t size, size_t offset, size_t original)
30 : filePtr_(file), fileSize_(size), fileOffset_(offset), fileOriginalOffset_(original)
31 {}
32
~FileSourceStream()33 FileSourceStream::~FileSourceStream()
34 {
35 fclose(filePtr_);
36 ResetReadBuffer();
37 }
38
CreateSourceStream(const string & pathName)39 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const string &pathName)
40 {
41 string realPath;
42 if (!PathToRealPath(pathName, realPath)) {
43 IMAGE_LOGE("[FileSourceStream]input the file path exception.");
44 return nullptr;
45 }
46 size_t size = 0;
47 if (!ImageUtils::GetFileSize(realPath, size)) {
48 IMAGE_LOGE("[FileSourceStream]get the file size fail.");
49 return nullptr;
50 }
51 FILE *filePtr = fopen(realPath.c_str(), "rb");
52 if (filePtr == nullptr) {
53 IMAGE_LOGE("[FileSourceStream]open file fail.");
54 return nullptr;
55 }
56 int64_t offset = ftell(filePtr);
57 if (offset < 0) {
58 IMAGE_LOGE("[FileSourceStream]get the position fail.");
59 fclose(filePtr);
60 return nullptr;
61 }
62 return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
63 }
64
CreateSourceStream(const int fd)65 unique_ptr<FileSourceStream> FileSourceStream::CreateSourceStream(const int fd)
66 {
67 size_t size = 0;
68
69 int dupFd = dup(fd);
70 if (dupFd < 0) {
71 IMAGE_LOGE("[FileSourceStream]Fail to dup fd.");
72 return nullptr;
73 }
74
75 if (!ImageUtils::GetFileSize(dupFd, size)) {
76 IMAGE_LOGE("[FileSourceStream]get the file size fail.");
77 return nullptr;
78 }
79 FILE *filePtr = fdopen(dupFd, "rb");
80 if (filePtr == nullptr) {
81 IMAGE_LOGE("[FileSourceStream]open file fail.");
82 return nullptr;
83 }
84
85 int ret = fseek(filePtr, 0, SEEK_SET);
86 if (ret != 0) {
87 IMAGE_LOGE("[FileSourceStream]Go to 0 position fail, ret:%{public}d.", ret);
88 }
89
90 int64_t offset = ftell(filePtr);
91 if (offset < 0) {
92 IMAGE_LOGE("[FileSourceStream]get the position fail.");
93 fclose(filePtr);
94 return nullptr;
95 }
96 return (unique_ptr<FileSourceStream>(new FileSourceStream(filePtr, size, offset, offset)));
97 }
98
Read(uint32_t desiredSize,DataStreamBuffer & outData)99 bool FileSourceStream::Read(uint32_t desiredSize, DataStreamBuffer &outData)
100 {
101 if (desiredSize == 0 || filePtr_ == nullptr) {
102 IMAGE_LOGE("[FileSourceStream]read stream input parameter exception.");
103 return false;
104 }
105 if (!GetData(desiredSize, outData)) {
106 IMAGE_LOGE("[FileSourceStream]read fail.");
107 return false;
108 }
109 fileOffset_ += outData.dataSize;
110 return true;
111 }
112
Peek(uint32_t desiredSize,DataStreamBuffer & outData)113 bool FileSourceStream::Peek(uint32_t desiredSize, DataStreamBuffer &outData)
114 {
115 if (desiredSize == 0 || filePtr_ == nullptr) {
116 IMAGE_LOGE("[FileSourceStream]peek stream input parameter exception.");
117 return false;
118 }
119 if (!GetData(desiredSize, outData)) {
120 IMAGE_LOGE("[FileSourceStream]peek fail.");
121 return false;
122 }
123 int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
124 if (ret != 0) {
125 IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
126 return false;
127 }
128 return true;
129 }
130
Read(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)131 bool FileSourceStream::Read(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
132 {
133 if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
134 IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
135 fileSize_:%{public}zu.",
136 desiredSize, bufferSize, fileSize_);
137 return false;
138 }
139 if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
140 IMAGE_LOGE("[FileSourceStream]read fail.");
141 return false;
142 }
143 fileOffset_ += readSize;
144 return true;
145 }
146
Peek(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)147 bool FileSourceStream::Peek(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
148 {
149 if (desiredSize == 0 || outBuffer == nullptr || desiredSize > bufferSize || desiredSize > fileSize_) {
150 IMAGE_LOGE("[FileSourceStream]input parameter exception, desiredSize:%{public}u, bufferSize:%{public}u, \
151 fileSize_:%{public}zu.",
152 desiredSize, bufferSize, fileSize_);
153 return false;
154 }
155 if (!GetData(desiredSize, outBuffer, bufferSize, readSize)) {
156 IMAGE_LOGE("[FileSourceStream]peek fail.");
157 return false;
158 }
159 int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
160 if (ret != 0) {
161 IMAGE_LOGE("[FileSourceStream]go to original position fail, ret:%{public}d.", ret);
162 return false;
163 }
164 return true;
165 }
166
Seek(uint32_t position)167 bool FileSourceStream::Seek(uint32_t position)
168 {
169 if (position > fileSize_) {
170 IMAGE_LOGE("[FileSourceStream]Seek the position greater than the file size, position:%{public}u.", position);
171 return false;
172 }
173 size_t targetPosition = position + fileOriginalOffset_;
174 fileOffset_ = ((targetPosition < fileSize_) ? targetPosition : fileSize_);
175 int ret = fseek(filePtr_, fileOffset_, SEEK_SET);
176 if (ret != 0) {
177 IMAGE_LOGE("[FileSourceStream]go to offset position fail, ret:%{public}d.", ret);
178 return false;
179 }
180 return true;
181 }
182
Tell()183 uint32_t FileSourceStream::Tell()
184 {
185 return fileOffset_;
186 }
187
GetData(uint32_t desiredSize,uint8_t * outBuffer,uint32_t bufferSize,uint32_t & readSize)188 bool FileSourceStream::GetData(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize)
189 {
190 if (fileSize_ == fileOffset_) {
191 IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
192 return false;
193 }
194 if (desiredSize > (fileSize_ - fileOffset_)) {
195 desiredSize = fileSize_ - fileOffset_;
196 }
197 size_t bytesRead = fread(outBuffer, sizeof(outBuffer[0]), desiredSize, filePtr_);
198 if (bytesRead < desiredSize) {
199 IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
200 return false;
201 }
202 readSize = desiredSize;
203 return true;
204 }
205
GetData(uint32_t desiredSize,DataStreamBuffer & outData)206 bool FileSourceStream::GetData(uint32_t desiredSize, DataStreamBuffer &outData)
207 {
208 if (fileSize_ == fileOffset_) {
209 IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_);
210 return false;
211 }
212
213 if (desiredSize == 0 || desiredSize > MALLOC_MAX_LENTH) {
214 IMAGE_LOGE("[FileSourceStream]Invalid value, desiredSize out of size.");
215 return false;
216 }
217
218 ResetReadBuffer();
219 readBuffer_ = static_cast<uint8_t *>(malloc(desiredSize));
220 if (readBuffer_ == nullptr) {
221 IMAGE_LOGE("[FileSourceStream]malloc the desiredSize fail.");
222 return false;
223 }
224 outData.bufferSize = desiredSize;
225 if (desiredSize > (fileSize_ - fileOffset_)) {
226 desiredSize = fileSize_ - fileOffset_;
227 }
228 size_t bytesRead = fread(readBuffer_, sizeof(uint8_t), desiredSize, filePtr_);
229 if (bytesRead < desiredSize) {
230 IMAGE_LOGE("[FileSourceStream]read fail, bytesRead:%{public}zu", bytesRead);
231 free(readBuffer_);
232 readBuffer_ = nullptr;
233 return false;
234 }
235 outData.inputStreamBuffer = static_cast<uint8_t *>(readBuffer_);
236 outData.dataSize = desiredSize;
237 return true;
238 }
239
GetStreamSize()240 size_t FileSourceStream::GetStreamSize()
241 {
242 return fileSize_;
243 }
244
GetDataPtr()245 uint8_t *FileSourceStream::GetDataPtr()
246 {
247 return nullptr;
248 }
249
GetStreamType()250 uint32_t FileSourceStream::GetStreamType()
251 {
252 return ImagePlugin::FILE_STREAM_TYPE;
253 }
254
ResetReadBuffer()255 void FileSourceStream::ResetReadBuffer()
256 {
257 if (readBuffer_ != nullptr) {
258 free(readBuffer_);
259 readBuffer_ = nullptr;
260 }
261 }
262 } // namespace Media
263 } // namespace OHOS
264