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