1 /*
2 * Copyright (C) 2023 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_utils.h"
17
18 #include <fcntl.h>
19 #include <sys/sendfile.h>
20 #include <sys/stat.h>
21
22 #include "media_log.h"
23 #include "media_file_utils.h"
24 #include "moving_photo_file_utils.h"
25 #include "database_adapter.h"
26 #include "dfx_utils.h"
27 #include "result_set_utils.h"
28 #include "media_column.h"
29 #include "image_packer.h"
30 #include "medialibrary_errno.h"
31 #include "medialibrary_tracer.h"
32 #include "medialibrary_type_const.h"
33 #include "medialibrary_operation.h"
34 #include "medialibrary_object_utils.h"
35 #include "picture.h"
36 #include "image_type.h"
37
38 using namespace std;
39
40 namespace OHOS {
41 namespace Media {
FileUtils()42 FileUtils::FileUtils() {}
43
~FileUtils()44 FileUtils::~FileUtils() {}
45
DeleteFile(const string & fileName)46 int FileUtils::DeleteFile(const string &fileName)
47 {
48 int ret = remove(fileName.c_str());
49 if (ret < 0) {
50 MEDIA_ERR_LOG("DeleteFile fail, ret: %{public}d, errno: %{public}d", ret, errno);
51 }
52 return ret;
53 }
54
IsFileExist(const string & fileName)55 bool FileUtils::IsFileExist(const string &fileName)
56 {
57 struct stat statInfo {};
58 return ((stat(fileName.c_str(), &statInfo)) == E_SUCCESS);
59 }
60
SaveImage(const string & filePath,void * output,size_t writeSize)61 int32_t FileUtils::SaveImage(const string &filePath, void *output, size_t writeSize)
62 {
63 const mode_t fileMode = 0644;
64 MediaLibraryTracer tracer;
65 tracer.Start("FileUtils::SaveImage");
66 string filePathTemp = filePath + ".high";
67 int fd = open(filePathTemp.c_str(), O_CREAT|O_WRONLY|O_TRUNC, fileMode);
68 if (fd < 0) {
69 MEDIA_ERR_LOG("fd.Get() < 0 fd %{public}d errno: %{public}d", fd, errno);
70 return E_ERR;
71 }
72 MEDIA_DEBUG_LOG("filePath: %{private}s, fd: %{public}d", filePath.c_str(), fd);
73
74 int ret = write(fd, output, writeSize);
75 close(fd);
76 if (ret < 0) {
77 MEDIA_ERR_LOG("write fail, ret: %{public}d, errno: %{public}d", ret, errno);
78 DeleteFile(filePathTemp);
79 return ret;
80 }
81
82 ret = rename(filePathTemp.c_str(), filePath.c_str());
83 if (ret < 0) {
84 MEDIA_ERR_LOG("rename fail, ret: %{public}d, errno: %{public}d", ret, errno);
85 DeleteFile(filePathTemp);
86 return ret;
87 }
88
89 return ret;
90 }
91
SavePicture(const string & imageId,std::shared_ptr<Media::Picture> & picture,bool isEdited,bool isLowQualityPicture)92 int32_t FileUtils::SavePicture(const string &imageId, std::shared_ptr<Media::Picture> &picture,
93 bool isEdited, bool isLowQualityPicture)
94 {
95 MediaLibraryTracer tracer;
96 // 通过imageid获取fileid 获取uri
97 if (picture == nullptr) {
98 return -1;
99 }
100 MEDIA_INFO_LOG("photoid: %{public}s", imageId.c_str());
101 MediaLibraryCommand cmd(OperationObject::FILESYSTEM_PHOTO, OperationType::QUERY);
102 string where = PhotoColumn::PHOTO_ID + " = ? ";
103 vector<string> whereArgs { imageId };
104 cmd.GetAbsRdbPredicates()->SetWhereClause(where);
105 cmd.GetAbsRdbPredicates()->SetWhereArgs(whereArgs);
106 vector<string> columns { MediaColumn::MEDIA_ID, MediaColumn::MEDIA_FILE_PATH, PhotoColumn::PHOTO_EDIT_TIME,
107 PhotoColumn::PHOTO_SUBTYPE, MediaColumn::MEDIA_MIME_TYPE};
108 tracer.Start("Query");
109 auto resultSet = DatabaseAdapter::Query(cmd, columns);
110 if (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK) {
111 tracer.Finish();
112 MEDIA_INFO_LOG("result set is empty");
113 return -1;
114 }
115 tracer.Finish();
116 string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
117 int fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
118 string sourcePath = isEdited ? MediaLibraryAssetOperations::GetEditDataSourcePath(path) : path;
119 //查询是否编辑 编辑目录下
120 string mime_type = GetStringVal(MediaColumn::MEDIA_MIME_TYPE, resultSet);
121 resultSet->Close();
122 if (mime_type == "") {
123 mime_type = "image/jpeg";
124 }
125 size_t sizeHeic = -1;
126 size_t pos = sourcePath.find_last_of('.');
127 string pathPos = sourcePath.substr(0, pos);
128 string pathHeic = pathPos + ".heic";
129 MediaFileUtils::GetFileSize(pathHeic, sizeHeic);
130 size_t sizeJpeg = -1;
131 string pathJpeg = pathPos + ".jpeg";
132 MediaFileUtils::GetFileSize(pathJpeg, sizeJpeg);
133
134 if (isLowQualityPicture && (sizeHeic > 0 || sizeJpeg > 0)) {
135 return -1;
136 }
137
138 int ret = DealPicture(mime_type, sourcePath, picture);
139 return ret;
140 }
141
SavePicture(const string & path,std::shared_ptr<Media::Picture> & picture,const std::string & mime_type,bool isEdited)142 int32_t FileUtils::SavePicture(const string &path, std::shared_ptr<Media::Picture> &picture,
143 const std::string &mime_type, bool isEdited)
144 {
145 MEDIA_INFO_LOG("SavePicture width %{public}d, heigh %{public}d, mime_type %{public}sd",
146 picture->GetMainPixel()->GetWidth(), picture->GetMainPixel()->GetHeight(), mime_type.c_str());
147 return DealPicture(mime_type, path, picture);
148 }
149
DealPicture(const std::string & mime_type,const std::string & path,std::shared_ptr<Media::Picture> & picture)150 int32_t FileUtils::DealPicture(const std::string &mime_type, const std::string &path,
151 std::shared_ptr<Media::Picture> &picture)
152 {
153 MediaLibraryTracer tracer;
154 tracer.Start("FileUtils::DealPicture");
155 MEDIA_INFO_LOG("DealPicture, path: %{public}s, mime_type: %{public}s",
156 MediaFileUtils::DesensitizePath(path).c_str(), mime_type.c_str());
157 if (picture == nullptr) {
158 MEDIA_ERR_LOG("picture is nullptr.");
159 return -1;
160 }
161 Media::ImagePacker imagePacker;
162 Media::PackOption packOption;
163 packOption.format = mime_type;
164 packOption.needsPackProperties = true;
165 packOption.desiredDynamicRange = EncodeDynamicRange::AUTO;
166 packOption.isEditScene = false;
167 size_t lastSlash = path.rfind('/');
168 CHECK_AND_RETURN_RET_LOG(lastSlash != string::npos && path.size() > (lastSlash + 1), E_INVALID_VALUES,
169 "Failed to check outputPath: %{public}s", path.c_str());
170 string tempOutputPath = path.substr(0, lastSlash) + "/temp_" + path.substr(lastSlash + 1);
171 int32_t ret = MediaFileUtils::CreateAsset(tempOutputPath);
172 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_FS_ERROR,
173 "Failed to create temp filters file %{private}s", tempOutputPath.c_str());
174 imagePacker.StartPacking(tempOutputPath, packOption);
175 imagePacker.AddPicture(*(picture));
176 imagePacker.FinalizePacking();
177 size_t size = -1;
178 MediaFileUtils::GetFileSize(tempOutputPath, size);
179 MEDIA_INFO_LOG("SavePicture end size: {public}%zu", size);
180 if (size == 0) {
181 CHECK_AND_PRINT_LOG(MediaFileUtils::DeleteFile(tempOutputPath),
182 "Failed to delete temp filters file, errno: %{public}d", errno);
183 return E_OK;
184 }
185 ret = rename(tempOutputPath.c_str(), path.c_str());
186 if (MediaFileUtils::IsFileExists(tempOutputPath)) {
187 MEDIA_INFO_LOG("file: %{public}s exists and needs to be deleted", tempOutputPath.c_str());
188 if (!MediaFileUtils::DeleteFile(tempOutputPath)) {
189 MEDIA_ERR_LOG("delete file: %{public}s failed", tempOutputPath.c_str());
190 }
191 }
192 return ret;
193 }
194
SaveVideo(const std::string & filePath,bool isEdited)195 int32_t FileUtils::SaveVideo(const std::string &filePath, bool isEdited)
196 {
197 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
198 string targetPath = filePath;
199 if (isEdited) {
200 targetPath = MediaLibraryAssetOperations::GetEditDataSourcePath(filePath);
201 }
202
203 if (!IsFileExist(tempPath)) {
204 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
205 }
206
207 if (!IsFileExist(targetPath)) {
208 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
209 }
210
211 MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
212 DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
213 return rename(tempPath.c_str(), targetPath.c_str());
214 }
215
SaveMovingPhotoVideo(const std::string & filePath)216 int32_t FileUtils::SaveMovingPhotoVideo(const std::string &filePath)
217 {
218 string tempPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
219 filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.')));
220 string targetPath;
221
222 string videoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(filePath);
223 string editVideoPath = MovingPhotoFileUtils::GetMovingPhotoVideoPath(
224 MediaLibraryAssetOperations::GetEditDataSourcePath(filePath));
225
226 if (!IsFileExist(tempPath)) {
227 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(tempPath).c_str());
228 }
229
230 if (IsFileExist(editVideoPath)) {
231 targetPath = editVideoPath;
232 } else if (IsFileExist(videoPath)) {
233 targetPath = videoPath;
234 } else {
235 MEDIA_ERR_LOG("file not exist: %{public}s", DfxUtils::GetSafePath(filePath).c_str());
236 }
237
238 MEDIA_INFO_LOG("video rename targetPath: %{public}s, tempPath: %{public}s",
239 DfxUtils::GetSafePath(targetPath).c_str(), DfxUtils::GetSafePath(tempPath).c_str());
240 return rename(tempPath.c_str(), targetPath.c_str());
241 }
242
DeleteTempVideoFile(const std::string & filePath)243 int32_t FileUtils::DeleteTempVideoFile(const std::string &filePath)
244 {
245 MEDIA_INFO_LOG("filePath: %{public}s", filePath.c_str());
246 string tempPath = filePath.substr(0, filePath.rfind('.')) + "_tmp" + filePath.substr(filePath.rfind('.'));
247 if (IsFileExist(tempPath)) {
248 return DeleteFile(tempPath);
249 }
250 return E_OK;
251 }
252 } // namespace Media
253 } // namespace OHOS