1 /*
2  * Copyright (C) 2024 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 #define MLOG_TAG "PhotoFileOperation"
16 
17 #include "photo_file_operation.h"
18 
19 #include <sstream>
20 
21 #include "media_log.h"
22 #include "medialibrary_errno.h"
23 #include "medialibrary_kvstore_utils.h"
24 #include "userfile_manager_types.h"
25 #include "media_file_utils.h"
26 #include "media_column.h"
27 #include "result_set_utils.h"
28 
29 namespace OHOS::Media {
ToString(const PhotoAssetInfo & photoInfo)30 std::string PhotoFileOperation::ToString(const PhotoAssetInfo &photoInfo)
31 {
32     std::stringstream ss;
33     ss << "PhotoAssetInfo[displayName: " << photoInfo.displayName << ", filePath: " << photoInfo.filePath
34        << ", dateModified: " << photoInfo.dateModified << ", subtype: " << photoInfo.subtype
35        << ", videoFilePath: " << photoInfo.videoFilePath << ", editDataFolder: " << photoInfo.editDataFolder
36        << ", thumbnailFolder: " << photoInfo.thumbnailFolder << "]";
37     return ss.str();
38 }
39 
40 /**
41  * @brief Copy Photo File, include photo file, video file and edit data folder.
42  */
CopyPhoto(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & targetPath)43 int32_t PhotoFileOperation::CopyPhoto(
44     const std::shared_ptr<NativeRdb::ResultSet> &resultSet, const std::string &targetPath)
45 {
46     if (resultSet == nullptr || targetPath.empty()) {
47         MEDIA_ERR_LOG("Media_Operation: CopyPhoto failed, resultSet is null or targetPath is empty");
48         return E_FAIL;
49     }
50     // Build the Original Photo Asset Info
51     PhotoFileOperation::PhotoAssetInfo sourcePhotoInfo;
52     sourcePhotoInfo.displayName = GetStringVal(MediaColumn::MEDIA_NAME, resultSet);
53     sourcePhotoInfo.filePath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
54     sourcePhotoInfo.subtype = GetInt32Val(PhotoColumn::PHOTO_SUBTYPE, resultSet);
55     sourcePhotoInfo.dateModified = GetInt64Val(MediaColumn::MEDIA_DATE_MODIFIED, resultSet);
56     sourcePhotoInfo.videoFilePath = this->FindVideoFilePath(sourcePhotoInfo);
57     sourcePhotoInfo.editDataFolder = this->FindEditDataFolder(sourcePhotoInfo);
58     // Build the Target Photo Asset Info
59     PhotoFileOperation::PhotoAssetInfo targetPhotoInfo;
60     targetPhotoInfo.displayName = sourcePhotoInfo.displayName;
61     targetPhotoInfo.filePath = targetPath;
62     targetPhotoInfo.subtype = sourcePhotoInfo.subtype;
63     targetPhotoInfo.dateModified = sourcePhotoInfo.dateModified;
64     // No need to copy video file if the Original Photo is not a moving photo.
65     if (!sourcePhotoInfo.videoFilePath.empty()) {
66         targetPhotoInfo.videoFilePath = this->GetVideoFilePath(targetPhotoInfo);
67     }
68     // No need to copy edit data folder if the Original Photo is not edited.
69     if (!sourcePhotoInfo.editDataFolder.empty()) {
70         targetPhotoInfo.editDataFolder = this->BuildEditDataFolder(targetPhotoInfo);
71     }
72     MEDIA_INFO_LOG("Media_Operation: sourcePhotoInfo: %{public}s, targetPhotoInfo: %{public}s",
73         this->ToString(sourcePhotoInfo).c_str(),
74         this->ToString(targetPhotoInfo).c_str());
75     return this->CopyPhoto(sourcePhotoInfo, targetPhotoInfo);
76 }
77 
78 /**
79  * @brief Copy thumbnail, include folder and astc data.
80  */
CopyThumbnail(const std::shared_ptr<NativeRdb::ResultSet> & resultSet,const std::string & targetPath,int64_t & newAssetId)81 int32_t PhotoFileOperation::CopyThumbnail(
82     const std::shared_ptr<NativeRdb::ResultSet> &resultSet, const std::string &targetPath, int64_t &newAssetId)
83 {
84     if (resultSet == nullptr || targetPath.empty()) {
85         MEDIA_ERR_LOG("Media_Operation: CopyPhoto failed, resultSet is null or targetPath is empty");
86         return E_FAIL;
87     }
88 
89     // Build the Original Photo Asset Info
90     PhotoFileOperation::PhotoAssetInfo sourcePhotoInfo;
91     sourcePhotoInfo.filePath = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
92     sourcePhotoInfo.thumbnailFolder = this->FindThumbnailFolder(sourcePhotoInfo);
93     if (sourcePhotoInfo.thumbnailFolder.empty()) {
94         MEDIA_INFO_LOG("Source thumbnail is empty, skip copy. thumbnailFolder:%{public}s",
95             sourcePhotoInfo.thumbnailFolder.c_str());
96         return E_FAIL;
97     }
98 
99     // copy folder
100     PhotoFileOperation::PhotoAssetInfo targetPhotoInfo;
101     targetPhotoInfo.filePath = targetPath;
102     targetPhotoInfo.thumbnailFolder = this->BuildThumbnailFolder(targetPhotoInfo);
103     int32_t opRet = this->CopyPhotoRelatedThumbnail(sourcePhotoInfo, targetPhotoInfo);
104     if (opRet != E_OK) {
105         return opRet;
106     }
107 
108     std::string dateTaken = to_string(GetInt64Val(MediaColumn::MEDIA_DATE_TAKEN, resultSet));
109     std::string oldAssetId = to_string(GetInt64Val(MediaColumn::MEDIA_ID, resultSet));
110     return HandleThumbnailAstcData(dateTaken, oldAssetId, to_string(newAssetId));
111 }
112 
HandleThumbnailAstcData(const std::string & dateTaken,const std::string & oldAssetId,const std::string & newAssetId)113 int32_t PhotoFileOperation::HandleThumbnailAstcData(const std::string &dateTaken, const std::string &oldAssetId,
114     const std::string &newAssetId)
115 {
116     // 取旧key拿value,然后在put新key和value(和旧的value一样)到kvstore中
117     string oldKey;
118     if (!MediaFileUtils::GenerateKvStoreKey(oldAssetId, dateTaken, oldKey)) {
119         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
120         return E_ERR;
121     }
122 
123     string newKey;
124     if (!MediaFileUtils::GenerateKvStoreKey(newAssetId, dateTaken, newKey)) {
125         MEDIA_ERR_LOG("GenerateKvStoreKey failed");
126         return E_ERR;
127     }
128 
129     int32_t err = MediaLibraryKvStoreUtils::CopyAstcDataToKvStoreByType(KvStoreValueType::MONTH_ASTC, oldKey, newKey);
130     if (err != E_OK) {
131         MEDIA_ERR_LOG("CopyAstcDataToKvStoreByType failed, err: %{public}d", err);
132         return err;
133     }
134 
135     err = MediaLibraryKvStoreUtils::CopyAstcDataToKvStoreByType(KvStoreValueType::YEAR_ASTC, oldKey, newKey);
136     if (err != E_OK) {
137         MEDIA_ERR_LOG("CopyAstcDataToKvStoreByType failed, err: %{public}d", err);
138         return err;
139     }
140     MEDIA_INFO_LOG("Success to copy thumbnail. oldKey:%{public}s, newKey:%{public}s", oldKey.c_str(), newKey.c_str());
141     return E_OK;
142 }
143 
144 /**
145  * @brief Copy Photo File, include photo file, video file and edit data folder.
146  */
CopyPhoto(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo)147 int32_t PhotoFileOperation::CopyPhoto(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
148     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo)
149 {
150     int32_t opRet = this->CopyPhotoFile(sourcePhotoInfo, targetPhotoInfo);
151     if (opRet != E_OK) {
152         return opRet;
153     }
154     opRet = this->CopyPhotoRelatedVideoFile(sourcePhotoInfo, targetPhotoInfo);
155     if (opRet != E_OK) {
156         return opRet;
157     }
158     return this->CopyPhotoRelatedExtraData(sourcePhotoInfo, targetPhotoInfo);
159 }
160 
161 /**
162  * @brief Get the video file path of the photo, without any check.
163  * @return the video file path of the photo. Only replace the suffix of file extension, such as .jpg to .mp4.
164  * @example if filePath is /xxx/.../xxx/123456789.jpg, then return /xxx/.../xxx/123456789.mp4.
165  */
GetVideoFilePath(const PhotoFileOperation::PhotoAssetInfo & photoInfo)166 std::string PhotoFileOperation::GetVideoFilePath(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
167 {
168     return MediaFileUtils::GetMovingPhotoVideoPath(photoInfo.filePath);
169 }
170 
171 /**
172  * @brief Get the video file path of the photo, without any check.
173  * @return the video file path of the photo. Only replace the suffix of file extension, such as .jpg to .mp4.
174  *         If the photo is not a moving photo, return an empty string.
175  *         If the photo's file path is empty, return an empty string.
176  *         If the photo is a moving photo, return the video file path of the photo.
177  */
FindVideoFilePath(const PhotoFileOperation::PhotoAssetInfo & photoInfo)178 std::string PhotoFileOperation::FindVideoFilePath(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
179 {
180     if (photoInfo.subtype != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
181         return "";
182     }
183     // If file path is empty, return empty string. Trace log will be printed in CopyPhotoFile.
184     if (photoInfo.filePath.empty()) {
185         return "";
186     }
187     std::string videoFilePath = this->GetVideoFilePath(photoInfo);
188     if (!MediaFileUtils::IsFileExists(videoFilePath)) {
189         MEDIA_WARN_LOG("Media_Operation: videoFilePath not exists, videoFilePath: %{public}s, Object: %{public}s.",
190             videoFilePath.c_str(),
191             this->ToString(photoInfo).c_str());
192         return "";
193     }
194     return videoFilePath;
195 }
196 
197 /**
198  * @brief Find the Relative Path of filePath.
199  * @return Relative Path.
200  *         If prefix of filePath is "/storage/cloud/files", return the relative path of cloud prefix.
201  *         If prefix of filePath is "/storage/media/local/files", return the relative path of local prefix.
202  *         Otherwise, return empty string.
203  */
FindRelativePath(const std::string & filePath)204 std::string PhotoFileOperation::FindRelativePath(const std::string &filePath)
205 {
206     std::string prefix = "/storage/cloud/files";
207     size_t pos = filePath.find(prefix);
208     if (pos != std::string::npos) {
209         return filePath.substr(pos + prefix.size());
210     }
211     prefix = "/storage/media/local/files";
212     pos = filePath.find(prefix);
213     if (pos != std::string::npos) {
214         return filePath.substr(pos + prefix.size());
215     }
216     MEDIA_ERR_LOG("Media_Operation: Find RelativePath failed, filePath: %{public}s", filePath.c_str());
217     return "";
218 }
219 
220 /**
221  * @brief Find the prefix of photo Data Folder.
222  * @return Return the prefix of photo Data Folder.
223  *         There are two prefixes, one is local, the other is cloud.
224  *         If the prefix of filePath is cloud, return "/storage/cloud/files/" + dataName.
225  *         If the prefix of filePath is local, return "/storage/media/local/files/" + dataName;
226  *         If the prefix of filePath is not found, return "".
227  */
FindPrefixDataFolder(const std::string & filePath,const std::string & dataName)228 std::string PhotoFileOperation::FindPrefixDataFolder(const std::string &filePath, const std::string &dataName)
229 {
230     std::string prefix = "/storage/cloud/files";
231     size_t pos = filePath.find(prefix);
232     if (pos != std::string::npos) {
233         return "/storage/cloud/files/" + dataName;
234     }
235     prefix = "/storage/media/local/files";
236     pos = filePath.find(prefix);
237     if (pos != std::string::npos) {
238         return "/storage/media/local/files/" + dataName;
239     }
240     MEDIA_WARN_LOG("Media_Operation: Get Prefix failed, filePath: %{public}s", filePath.c_str());
241     return "";
242 }
243 
244 /**
245  * @brief Find the prefix of Edit Data Folder.
246  * @return Return the prefix of Edit Data Folder.
247  *         There are two prefixes, one is local, the other is cloud.
248  *         If the prefix of filePath is cloud, return "/storage/cloud/files/.editData".
249  *         If the prefix of filePath is local, return "/storage/media/local/files/.editData";
250  *         If the prefix of filePath is not found, return "".
251  */
FindPrefixOfEditDataFolder(const std::string & filePath)252 std::string PhotoFileOperation::FindPrefixOfEditDataFolder(const std::string &filePath)
253 {
254     return FindPrefixDataFolder(filePath, ".editData");
255 }
256 
257 /**
258  * @brief Find the prefix of thumbs Data Folder.
259  * @return Return the prefix of thumbs Data Folder.
260  *         There are two prefixes, one is local, the other is cloud.
261  *         If the prefix of filePath is cloud, return "/storage/cloud/files/.thumbs".
262  *         If the prefix of filePath is local, return "/storage/media/local/files/.thumbs";
263  *         If the prefix of filePath is not found, return "".
264  */
FindPrefixOfThumbnailFolder(const std::string & filePath)265 std::string PhotoFileOperation::FindPrefixOfThumbnailFolder(const std::string &filePath)
266 {
267     return FindPrefixDataFolder(filePath, ".thumbs");
268 }
269 
270 /**
271  * @brief Build the Edit Data Folder for the Photo file, without any check.
272  * @return Return the Edit Data Folder for the Photo file.
273  *         If the filePath is cloud, return "/storage/cloud/files/.editData/" + the relativePath of Photo file.
274  *         If the filePath is local, return "/storage/media/local/files/.editData/" + the relativePath of Photo file.
275  *         If the filePath is not identified, return "".
276  */
BuildEditDataFolder(const PhotoFileOperation::PhotoAssetInfo & photoInfo)277 std::string PhotoFileOperation::BuildEditDataFolder(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
278 {
279     std::string prefix = this->FindPrefixOfEditDataFolder(photoInfo.filePath);
280     std::string relativePath = this->FindRelativePath(photoInfo.filePath);
281     if (prefix.empty() || relativePath.empty()) {
282         return "";
283     }
284     return prefix + relativePath;
285 }
286 
287 /**
288  * @brief Build the thumbs Data Folder for the Photo file, without any check.
289  * @return Return the thumbs Data Folder for the Photo file.
290  *         If the filePath is cloud, return "/storage/cloud/files/.thumbs/" + the relativePath of Photo file.
291  *         If the filePath is local, return "/storage/media/local/files/.thumbs/" + the relativePath of Photo file.
292  *         If the filePath is not identified, return "".
293  */
BuildThumbnailFolder(const PhotoFileOperation::PhotoAssetInfo & photoInfo)294 std::string PhotoFileOperation::BuildThumbnailFolder(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
295 {
296     std::string prefix = this->FindPrefixOfThumbnailFolder(photoInfo.filePath);
297     std::string relativePath = this->FindRelativePath(photoInfo.filePath);
298     if (prefix.empty() || relativePath.empty()) {
299         return "";
300     }
301     return prefix + relativePath;
302 }
303 
304 /**
305  * @brief Find the thumbs Data Folder for the Photo file.
306  * @return Return the thumbs Data Folder path. If the thumbs Data Folder is invalid, return empty string.
307  *         If the thumbs Data Folder is not exist, has 3 scenario:
308  *         1. The photo file is not thumbs. Normal scenario.
309  *         2. The photo file is not MOVING_PHOTO. Noraml scenario.
310  *         3. The photo file is thumbs or MOVING_PHOTO, but the thumbs Data Folder is not exist. Exceptional scenario.
311  */
FindThumbnailFolder(const PhotoFileOperation::PhotoAssetInfo & photoInfo)312 std::string PhotoFileOperation::FindThumbnailFolder(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
313 {
314     std::string thumbnailFolderPath = this->BuildThumbnailFolder(photoInfo);
315     if (!thumbnailFolderPath.empty() && !MediaFileUtils::IsFileExists(thumbnailFolderPath)) {
316         MEDIA_INFO_LOG("Media_Operation: thumbnailFolder not exists, Object: %{public}s.",
317             this->ToString(photoInfo).c_str());
318         return "";
319     }
320     return thumbnailFolderPath;
321 }
322 
323 /**
324  * @brief Find the Edit Data Folder for the Photo file.
325  * @return Return the Edit Data Folder path. If the Edit Data Folder is invalid, return empty string.
326  *         If the Edit Data Folder is not exist, has 3 scenario:
327  *         1. The photo file is not edited. Normal scenario.
328  *         2. The photo file is not MOVING_PHOTO. Noraml scenario.
329  *         3. The photo file is edited or MOVING_PHOTO, but the Edit Data Folder is not exist. Exceptional scenario.
330  */
FindEditDataFolder(const PhotoFileOperation::PhotoAssetInfo & photoInfo)331 std::string PhotoFileOperation::FindEditDataFolder(const PhotoFileOperation::PhotoAssetInfo &photoInfo)
332 {
333     std::string editDataFolderPath = this->BuildEditDataFolder(photoInfo);
334     if (!editDataFolderPath.empty() && !MediaFileUtils::IsFileExists(editDataFolderPath)) {
335         MEDIA_INFO_LOG("Media_Operation: EditDataFolder not exists, It may not be edited photo or moving photo. "
336                        "Object: %{public}s.",
337             this->ToString(photoInfo).c_str());
338         return "";
339     }
340     return editDataFolderPath;
341 }
342 
343 /**
344  * @brief Copy Photo File, only include the photo file defined in the Photos table.
345  * @return E_OK if success,
346  *         E_INVALID_PATH if the source file or target file is invalid,
347  *         E_FILE_OPER_FAIL if the copy operation failed.
348  */
CopyPhotoFile(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo)349 int32_t PhotoFileOperation::CopyPhotoFile(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
350     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo)
351 {
352     std::string srcPath = sourcePhotoInfo.filePath;
353     std::string targetPath = targetPhotoInfo.filePath;
354     int64_t dateModified = targetPhotoInfo.dateModified;
355     // If File Path is empty, return E_INVALID_PATH.
356     if (srcPath.empty() || targetPath.empty()) {
357         MEDIA_ERR_LOG("Media_Operation: CopyPhotoFile failed, srcPath or targetPath is empty. "
358                       "Source Object: %{public}s, Target Object: %{public}s",
359             this->ToString(sourcePhotoInfo).c_str(),
360             this->ToString(targetPhotoInfo).c_str());
361         return E_INVALID_PATH;
362     }
363     int32_t opRet = this->CopyFile(srcPath, targetPath);
364     if (opRet != E_OK) {
365         MEDIA_ERR_LOG("Media_Operation: CopyPhoto failed, srcPath: %{public}s, targetPath: %{public}s",
366             srcPath.c_str(),
367             targetPath.c_str());
368         return opRet;
369     }
370     MediaFileUtils::ModifyFile(targetPath, dateModified / MSEC_TO_SEC);
371     MEDIA_INFO_LOG("Media_Operation: CopyPhotoFile success, srcPath: %{public}s, targetPath: %{public}s",
372         srcPath.c_str(),
373         targetPath.c_str());
374     return E_OK;
375 }
376 
377 /**
378  * @brief Copy Photo File, only include the vide file related to the photo file defined in the Photos table.
379  * @return E_OK if success or not MOVING_PHOTO or video file empty,
380  *         E_INVALID_PATH if the source file or target file is invalid,
381  *         E_FILE_OPER_FAIL if the copy operation failed.
382  */
CopyPhotoRelatedVideoFile(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo)383 int32_t PhotoFileOperation::CopyPhotoRelatedVideoFile(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
384     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo)
385 {
386     // If photoSubtype is MOVING_PHOTO, copy video file.
387     if (sourcePhotoInfo.subtype != static_cast<int32_t>(PhotoSubType::MOVING_PHOTO)) {
388         return E_OK;
389     }
390     std::string srcVideoPath = sourcePhotoInfo.videoFilePath;
391     std::string targetVideoPath = targetPhotoInfo.videoFilePath;
392     int64_t dateModified = targetPhotoInfo.dateModified;
393     // If video file is empty, return E_OK. Trace log will be printed in FindVideoFilePath.
394     if (srcVideoPath.empty() || targetVideoPath.empty()) {
395         return E_OK;
396     }
397     int32_t opRet = this->CopyFile(srcVideoPath, targetVideoPath);
398     if (opRet != E_OK) {
399         MEDIA_ERR_LOG("Media_Operation: CopyPhoto Video failed, srcPath: %{public}s, targetPath: %{public}s",
400             srcVideoPath.c_str(),
401             targetVideoPath.c_str());
402         return opRet;
403     }
404     MediaFileUtils::ModifyFile(targetVideoPath, dateModified / MSEC_TO_SEC);
405     MEDIA_INFO_LOG("Media_Operation: CopyPhotoRelatedVideoFile success, srcPath: %{public}s, targetPath: %{public}s",
406         srcVideoPath.c_str(),
407         targetVideoPath.c_str());
408     return E_OK;
409 }
410 
CopyPhotoRelatedData(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo,const std::string & srcFolder,const std::string & targetFolder)411 int32_t PhotoFileOperation::CopyPhotoRelatedData(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
412     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo,
413     const std::string& srcFolder, const std::string& targetFolder)
414 {
415     if (srcFolder.empty() || targetFolder.empty()) {
416         return E_OK;
417     }
418     if (!MediaFileUtils::IsFileExists(srcFolder)) {
419         MEDIA_ERR_LOG("Media_Operation: %{public}s doesn't exist. %{public}s",
420             srcFolder.c_str(), this->ToString(sourcePhotoInfo).c_str());
421         return E_NO_SUCH_FILE;
422     }
423     int32_t opRet = MediaFileUtils::CopyDirectory(srcFolder, targetFolder);
424     if (opRet != E_OK) {
425         MEDIA_ERR_LOG("Media_Operation: CopyPhoto extraData failed, sourceInfo: %{public}s, targetInfo: %{public}s",
426             this->ToString(sourcePhotoInfo).c_str(), this->ToString(targetPhotoInfo).c_str());
427         return opRet;
428     }
429     MEDIA_INFO_LOG("Media_Operation: CopyPhotoRelatedExtraData success, sourceInfo:%{public}s, targetInfo:%{public}s",
430         this->ToString(sourcePhotoInfo).c_str(), this->ToString(targetPhotoInfo).c_str());
431     return E_OK;
432 }
433 
434 /**
435  * @brief Copy the Edit Data.
436  * @return E_OK if success or not edited photo.
437  *         E_NO_SUCH_FILE if the source Edit Data Folder not exits.
438  *         E_FAIL if the copy operation failed.
439  */
CopyPhotoRelatedExtraData(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo)440 int32_t PhotoFileOperation::CopyPhotoRelatedExtraData(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
441     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo)
442 {
443     std::string srcEditDataFolder = sourcePhotoInfo.editDataFolder;
444     std::string targetEditDataFolder = targetPhotoInfo.editDataFolder;
445     return CopyPhotoRelatedData(sourcePhotoInfo, targetPhotoInfo, srcEditDataFolder, targetEditDataFolder);
446 }
447 
448 /**
449  * @brief Copy the thumbnail Data.
450  * @return E_OK if success or not thumbnail folder.
451  *         E_NO_SUCH_FILE if the source Edit Data Folder not exits.
452  *         E_FAIL if the copy operation failed.
453  */
CopyPhotoRelatedThumbnail(const PhotoFileOperation::PhotoAssetInfo & sourcePhotoInfo,const PhotoFileOperation::PhotoAssetInfo & targetPhotoInfo)454 int32_t PhotoFileOperation::CopyPhotoRelatedThumbnail(const PhotoFileOperation::PhotoAssetInfo &sourcePhotoInfo,
455     const PhotoFileOperation::PhotoAssetInfo &targetPhotoInfo)
456 {
457     std::string srcThumbnailFolder = sourcePhotoInfo.thumbnailFolder;
458     std::string targetThumbnailFolder = targetPhotoInfo.thumbnailFolder;
459     int32_t opRet = CopyPhotoRelatedData(sourcePhotoInfo, targetPhotoInfo, srcThumbnailFolder, targetThumbnailFolder);
460     if (opRet != E_OK) {
461         MEDIA_ERR_LOG("Media_Operation: CopyPhoto thumbnail failed, srcPath: %{public}s, targetPath: %{public}s",
462             srcThumbnailFolder.c_str(), targetThumbnailFolder.c_str());
463         return opRet;
464     }
465 
466     return E_OK;
467 }
468 
469 /**
470  * @brief Copy File.
471  * @return E_OK if success,
472  *         E_INVALID_PATH if the source file or target file is invalid,
473  *         E_FILE_OPER_FAIL if the copy operation failed.
474  */
CopyFile(const std::string & srcPath,std::string & targetPath)475 int32_t PhotoFileOperation::CopyFile(const std::string &srcPath, std::string &targetPath)
476 {
477     if (srcPath.empty() || !MediaFileUtils::IsFileExists((srcPath)) || !MediaFileUtils::IsFileValid(srcPath)) {
478         MEDIA_ERR_LOG("Media_Operation: source file invalid! srcPath: %{public}s", srcPath.c_str());
479         return E_INVALID_PATH;
480     }
481     if (targetPath.empty()) {
482         MEDIA_ERR_LOG("Media_Operation: target file invalid! targetPath: %{public}s", targetPath.c_str());
483         return E_INVALID_PATH;
484     }
485     bool opRet = MediaFileUtils::CopyFileUtil(srcPath, targetPath);
486     opRet = opRet && MediaFileUtils::IsFileExists(targetPath);
487     if (!opRet) {
488         MEDIA_ERR_LOG("Media_Operation: CopyFile failed, filePath: %{public}s, errmsg: %{public}s",
489             srcPath.c_str(),
490             strerror(errno));
491         return E_FILE_OPER_FAIL;
492     }
493     return E_OK;
494 }
495 }  // namespace OHOS::Media