• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define MLOG_TAG "MediaLibraryBackupUtils"
17 
18 #include "backup_file_utils.h"
19 
20 #include <utime.h>
21 #include <sys/types.h>
22 
23 #include "backup_const_column.h"
24 #include "scanner_utils.h"
25 #include "media_file_uri.h"
26 #include "metadata_extractor.h"
27 #include "mimetype_utils.h"
28 #include "medialibrary_errno.h"
29 #include "media_log.h"
30 #include "media_file_utils.h"
31 #include "medialibrary_asset_operations.h"
32 #include "medialibrary_data_manager_utils.h"
33 #include "moving_photo_file_utils.h"
34 
35 namespace OHOS {
36 namespace Media {
37 const string DEFAULT_IMAGE_NAME = "IMG_";
38 const string DEFAULT_VIDEO_NAME = "VID_";
39 const string DEFAULT_AUDIO_NAME = "AUD_";
40 const string LOW_QUALITY_PATH = "Documents/cameradata/";
41 const size_t INVALID_RET = -1;
42 const int32_t APP_TWIN_DATA_START = 128;
43 const int32_t APP_TWIN_DATA_END = 147;
44 
45 constexpr int ASSET_MAX_COMPLEMENT_ID = 999;
46 std::shared_ptr<DataShare::DataShareHelper> BackupFileUtils::sDataShareHelper_ = nullptr;
47 std::shared_ptr<FileAccessHelper> BackupFileUtils::fileAccessHelper_ = std::make_shared<FileAccessHelper>();
48 
GetValidPath(string & filePath)49 bool FileAccessHelper::GetValidPath(string &filePath)
50 {
51     if (access(filePath.c_str(), F_OK) == 0) {
52         return true;
53     }
54 
55     string resultPath = filePath;
56     size_t pos = 0;
57     while ((pos = resultPath.find("/", pos + 1)) != string::npos) {
58         string curPath = resultPath.substr(0, pos);
59         if (!ConvertCurrentPath(curPath, resultPath)) {
60             MEDIA_ERR_LOG("convert fail, path: %{public}s", MediaFileUtils::DesensitizePath(filePath).c_str());
61             return false;
62         }
63     }
64 
65     string curPath = resultPath;
66     if (!ConvertCurrentPath(curPath, resultPath)) {
67         MEDIA_ERR_LOG("convert fail, path: %{public}s", MediaFileUtils::DesensitizePath(filePath).c_str());
68         return false;
69     }
70 
71     filePath = resultPath;
72     return true;
73 }
74 
ConvertCurrentPath(string & curPath,string & resultPath)75 bool FileAccessHelper::ConvertCurrentPath(string &curPath, string &resultPath)
76 {
77     if (access(curPath.c_str(), F_OK) == 0) {
78         return true;
79     }
80 
81     string parentDir = filesystem::path(curPath).parent_path().string();
82     transform(curPath.begin(), curPath.end(), curPath.begin(), ::tolower);
83     {
84         std::lock_guard<std::mutex> guard(mapMutex);
85         if (pathMap.find(curPath) != pathMap.end()) {
86             resultPath.replace(0, curPath.length(), pathMap[curPath]);
87             return true;
88         }
89     }
90     if (!MediaFileUtils::IsFileExists(parentDir)) {
91         MEDIA_WARN_LOG("%{public}s doesn't exist, skip.", parentDir.c_str());
92         return false;
93     }
94     for (const auto &entry : filesystem::directory_iterator(parentDir,
95         std::filesystem::directory_options::skip_permission_denied)) {
96         string entryPath = entry.path();
97         transform(entryPath.begin(), entryPath.end(), entryPath.begin(), ::tolower);
98         if (entryPath == curPath) {
99             resultPath.replace(0, curPath.length(), entry.path());
100             {
101                 std::lock_guard<std::mutex> guard(mapMutex);
102                 pathMap[curPath] = entry.path();
103             }
104             return true;
105         }
106     }
107 
108     return false;
109 }
110 
FillMetadata(std::unique_ptr<Metadata> & data)111 int32_t BackupFileUtils::FillMetadata(std::unique_ptr<Metadata> &data)
112 {
113     int32_t err = GetFileMetadata(data);
114     if (err != E_OK) {
115         MEDIA_ERR_LOG("failed to get file metadata");
116         return err;
117     }
118     if (data->GetFileMediaType() == MEDIA_TYPE_IMAGE) {
119         err = MetadataExtractor::ExtractImageMetadata(data);
120     } else {
121         err = MetadataExtractor::ExtractAVMetadata(data, Scene::AV_META_SCENE_CLONE);
122         MEDIA_INFO_LOG("Extract av metadata end");
123     }
124     if (err != E_OK) {
125         MEDIA_ERR_LOG("failed to extension data");
126         return err;
127     }
128     return E_OK;
129 }
130 
ConvertLowQualityPath(int32_t sceneCode,const std::string & filePath,const string & relativePath)131 string BackupFileUtils::ConvertLowQualityPath(int32_t sceneCode, const std::string &filePath,
132     const string &relativePath)
133 {
134     string result = filePath;
135     size_t displayNameIndex = result.rfind("/");
136     if (displayNameIndex == string::npos) {
137         return result;
138     }
139     std::string displayName = result.substr(displayNameIndex + 1);
140     size_t dotPos = displayName.find_last_of(".");
141     if (dotPos != string::npos) {
142         displayName.replace(dotPos, displayName.length() - dotPos, ".camera");
143     }
144     size_t pos = result.find(relativePath);
145     if (pos == string::npos) {
146         return result;
147     }
148     string publicPath = result.substr(0, pos + 1);
149     result = publicPath + LOW_QUALITY_PATH + displayName;
150     return result;
151 }
152 
GetFileMetadata(std::unique_ptr<Metadata> & data)153 int32_t BackupFileUtils::GetFileMetadata(std::unique_ptr<Metadata> &data)
154 {
155     std::string path = data->GetFilePath();
156     struct stat statInfo {};
157     if (stat(path.c_str(), &statInfo) != 0) {
158         MEDIA_ERR_LOG("stat syscall err %{public}d", errno);
159         return E_FAIL;
160     }
161     data->SetFileSize(statInfo.st_size);
162     auto dateModified = static_cast<int64_t>(MediaFileUtils::Timespec2Millisecond(statInfo.st_mtim));
163     if (dateModified == 0) {
164         dateModified = MediaFileUtils::UTCTimeMilliSeconds();
165         MEDIA_WARN_LOG("Invalid dateModified from st_mtim, use current time instead: %{public}lld",
166             static_cast<long long>(dateModified));
167     }
168     if (dateModified != 0 && data->GetFileDateModified() == 0) {
169         data->SetFileDateModified(dateModified);
170     }
171     string extension = ScannerUtils::GetFileExtension(data->GetFileName()); // in case when trashed or hidden
172     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension);
173     data->SetFileExtension(extension);
174     data->SetFileMimeType(mimeType);
175     return E_OK;
176 }
177 
GarbleFilePath(const std::string & filePath,int32_t sceneCode,std::string cloneFilePath)178 string BackupFileUtils::GarbleFilePath(const std::string &filePath, int32_t sceneCode, std::string cloneFilePath)
179 {
180     if (filePath.empty()) {
181         return filePath;
182     }
183     size_t displayNameIndex = filePath.rfind("/");
184     if (displayNameIndex == string::npos || displayNameIndex + 1 >= filePath.size()) {
185         return filePath;
186     }
187     std::string garbleDisplayName = GarbleFileName(filePath.substr(displayNameIndex + 1));
188     std::string path;
189     if (sceneCode == UPGRADE_RESTORE_ID) {
190         path = filePath.substr(0, displayNameIndex).replace(0, UPGRADE_FILE_DIR.length(), GARBLE);
191     } else if (sceneCode == DUAL_FRAME_CLONE_RESTORE_ID) {
192         path = filePath.substr(0, displayNameIndex).replace(0, GARBLE_DUAL_FRAME_CLONE_DIR.length(), GARBLE);
193     } else if (sceneCode == CLONE_RESTORE_ID) {
194         path = filePath.substr(0, displayNameIndex).replace(0, cloneFilePath.length(), GARBLE);
195     } else if (sceneCode == I_PHONE_CLONE_RESTORE) {
196         path = filePath.substr(0, displayNameIndex).replace(0, OTHER_CLONE_PATH.length(), GARBLE);
197     } else if (sceneCode == OTHERS_PHONE_CLONE_RESTORE) {
198         path = filePath.substr(0, displayNameIndex).replace(0, OTHER_CLONE_PATH.length(), GARBLE);
199     } else if (sceneCode == LITE_PHONE_CLONE_RESTORE) {
200         path = filePath.substr(0, displayNameIndex).replace(0, OTHER_CLONE_PATH.length(), GARBLE);
201     } else {
202         path = filePath.substr(0, displayNameIndex);
203     }
204     path += "/" + garbleDisplayName;
205     return path;
206 }
207 
GarbleFileName(const std::string & fileName)208 string BackupFileUtils::GarbleFileName(const std::string &fileName)
209 {
210     if (fileName.empty()) {
211         return fileName;
212     }
213     if (fileName.find("Screenshot_") == 0 || fileName.find("IMG_") == 0 || fileName.find("VID_") == 0 ||
214         fileName.find("SVID_") == 0) {
215         return fileName;
216     }
217     size_t titleIndex = fileName.rfind(".");
218     if (titleIndex == string::npos) {
219         titleIndex = fileName.size();
220     }
221     if (titleIndex <= GARBLE.size() * GARBLE_UNIT) {
222         return fileName;
223     }
224     return GARBLE + fileName.substr(GARBLE.size());
225 }
226 
CreateAssetPathById(int32_t fileId,int32_t mediaType,const string & extension,string & filePath)227 int32_t BackupFileUtils::CreateAssetPathById(int32_t fileId, int32_t mediaType, const string &extension,
228     string &filePath)
229 {
230     int32_t bucketNum = 0;
231     int32_t errCode = MediaFileUri::CreateAssetBucket(fileId, bucketNum);
232     if (errCode != E_OK) {
233         return errCode;
234     }
235 
236     string realName;
237     errCode = CreateAssetRealName(fileId, mediaType, extension, realName);
238     if (errCode != E_OK) {
239         return errCode;
240     }
241 
242     string dirPath = (mediaType == MediaType::MEDIA_TYPE_AUDIO ? RESTORE_AUDIO_CLOUD_DIR : RESTORE_CLOUD_DIR) + "/" +
243         to_string(bucketNum);
244     string localDirPath = GetReplacedPathByPrefixType(PrefixType::CLOUD, PrefixType::LOCAL, dirPath);
245     if (!MediaFileUtils::IsFileExists(localDirPath)) {
246         bool ret = MediaFileUtils::CreateDirectory(localDirPath);
247         errCode = ret? E_OK: E_CHECK_DIR_FAIL;
248     }
249     if (errCode != E_OK) {
250         MEDIA_ERR_LOG("Create Dir Failed! localDirPath=%{private}s", localDirPath.c_str());
251         return errCode;
252     }
253 
254     filePath = dirPath + "/" + realName;
255     return E_OK;
256 }
257 
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)258 int32_t BackupFileUtils::CreateAssetRealName(int32_t fileId, int32_t mediaType,
259     const string &extension, string &name)
260 {
261     string fileNumStr = to_string(fileId);
262     if (fileId <= ASSET_MAX_COMPLEMENT_ID) {
263         size_t fileIdLen = fileNumStr.length();
264         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
265     }
266 
267     string mediaTypeStr;
268     switch (mediaType) {
269         case MediaType::MEDIA_TYPE_IMAGE:
270             mediaTypeStr = DEFAULT_IMAGE_NAME;
271             break;
272         case MediaType::MEDIA_TYPE_VIDEO:
273             mediaTypeStr = DEFAULT_VIDEO_NAME;
274             break;
275         case MediaType::MEDIA_TYPE_AUDIO:
276             mediaTypeStr = DEFAULT_AUDIO_NAME;
277             break;
278         default:
279             MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
280             return E_INVALID_VALUES;
281     }
282     name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds()) + "_" + fileNumStr + "." + extension;
283     return E_OK;
284 }
285 
GetFullPathByPrefixType(PrefixType prefixType,const std::string & relativePath)286 std::string BackupFileUtils::GetFullPathByPrefixType(PrefixType prefixType, const std::string &relativePath)
287 {
288     std::string fullPath;
289     auto it = PREFIX_MAP.find(prefixType);
290     if (it == PREFIX_MAP.end()) {
291         MEDIA_ERR_LOG("Get path prefix failed: %{public}d", prefixType);
292         return fullPath;
293     }
294     fullPath = it->second + relativePath;
295     return fullPath;
296 }
297 
CreatePath(int32_t mediaType,const std::string & displayName,std::string & path)298 int32_t BackupFileUtils::CreatePath(int32_t mediaType, const std::string &displayName, std::string &path)
299 {
300     int32_t uniqueId = MediaLibraryAssetOperations::CreateAssetUniqueId(mediaType);
301     int32_t errCode = BackupFileUtils::CreateAssetPathById(uniqueId, mediaType,
302         MediaFileUtils::GetExtensionFromPath(displayName), path);
303     if (errCode != E_OK) {
304         MEDIA_ERR_LOG("Create path failed, errCode: %{public}d", errCode);
305         path.clear();
306         return errCode;
307     }
308     return E_OK;
309 }
310 
PreparePath(const std::string & path)311 int32_t BackupFileUtils::PreparePath(const std::string &path)
312 {
313     size_t index = path.rfind("/");
314     if (index == std::string::npos || index == path.length() - 1) {
315         MEDIA_ERR_LOG("Parse directory path failed: %{private}s", path.c_str());
316         return E_CHECK_DIR_FAIL;
317     }
318     std::string dirPath = path.substr(0, index);
319     if (!MediaFileUtils::IsFileExists(dirPath) && !MediaFileUtils::CreateDirectory(dirPath)) {
320         MEDIA_ERR_LOG("Directory path doesn't exist and was created failed: %{public}s", dirPath.c_str());
321         return E_CHECK_DIR_FAIL;
322     }
323     return E_OK;
324 }
325 
GetReplacedPathByPrefixType(PrefixType srcPrefixType,PrefixType dstPrefixType,const std::string & path)326 std::string BackupFileUtils::GetReplacedPathByPrefixType(PrefixType srcPrefixType, PrefixType dstPrefixType,
327     const std::string &path)
328 {
329     std::string replacedPath;
330     if (PREFIX_MAP.count(srcPrefixType) == 0 || PREFIX_MAP.count(dstPrefixType) == 0) {
331         MEDIA_ERR_LOG("Get source or destination prefix failed: %{public}d, %{public}d", srcPrefixType, dstPrefixType);
332         return replacedPath;
333     }
334     std::string srcPrefix = PREFIX_MAP.at(srcPrefixType);
335     std::string dstPrefix = PREFIX_MAP.at(dstPrefixType);
336     replacedPath = path;
337     replacedPath.replace(0, srcPrefix.length(), dstPrefix);
338     return replacedPath;
339 }
340 
MoveFile(const string & oldPath,const string & newPath,int32_t sceneCode)341 int32_t BackupFileUtils::MoveFile(const string &oldPath, const string &newPath, int32_t sceneCode)
342 {
343     bool errRet = false;
344     if (!MediaFileUtils::IsFileExists(oldPath)) {
345         MEDIA_ERR_LOG("old path: %{public}s is not exists.", GarbleFilePath(oldPath, sceneCode).c_str());
346         return E_NO_SUCH_FILE;
347     } else if (MediaFileUtils::IsFileExists(newPath)) {
348         MEDIA_ERR_LOG("new path: %{public}s is exists.", GarbleFilePath(newPath, sceneCode).c_str());
349         return E_FILE_EXIST;
350     }
351     return rename(oldPath.c_str(), newPath.c_str());
352 }
353 
ModifyFile(const std::string path,int64_t modifiedTime)354 void BackupFileUtils::ModifyFile(const std::string path, int64_t modifiedTime)
355 {
356     if (modifiedTime <= 0) {
357         MEDIA_ERR_LOG("ModifyTime error!");
358         return;
359     }
360     struct utimbuf buf;
361     buf.actime = modifiedTime; // second
362     buf.modtime = modifiedTime; // second
363     int ret = utime(path.c_str(), &buf);
364     if (ret != 0) {
365         MEDIA_ERR_LOG("Modify file failed: %{public}d", ret);
366     }
367 }
368 
IsLowQualityImage(std::string & filePath,int32_t sceneCode,string relativePath,bool hasLowQualityImage)369 int32_t BackupFileUtils::IsLowQualityImage(std::string &filePath, int32_t sceneCode,
370     string relativePath, bool hasLowQualityImage)
371 {
372     struct stat statInfo {};
373     std::string garbledFilePath = BackupFileUtils::GarbleFilePath(filePath, sceneCode);
374     if (!hasLowQualityImage) {
375         MEDIA_ERR_LOG("Invalid file (%{public}s), no low quality image, err: %{public}d", garbledFilePath.c_str(),
376             errno);
377         return E_FAIL;
378     }
379     string realPath = ConvertLowQualityPath(sceneCode, filePath, relativePath);
380     if (stat(realPath.c_str(), &statInfo) != E_SUCCESS) {
381         MEDIA_ERR_LOG("Invalid Low quality image! file:%{public}s, err:%{public}d", garbledFilePath.c_str(), errno);
382         return E_NO_SUCH_FILE;
383     }
384     MEDIA_INFO_LOG("Low quality image! file: %{public}s", garbledFilePath.c_str());
385     filePath = realPath;
386     if (statInfo.st_mode & S_IFDIR) {
387         MEDIA_ERR_LOG("Invalid file (%{public}s), is a directory", garbledFilePath.c_str());
388         return E_FAIL;
389     }
390     if (statInfo.st_size <= 0) {
391         MEDIA_ERR_LOG("Invalid file (%{public}s), get size (%{public}lld) <= 0", garbledFilePath.c_str(),
392             (long long)statInfo.st_size);
393         return E_FAIL;
394     }
395     return E_OK;
396 }
397 
IsFileValid(std::string & filePath,int32_t sceneCode,string relativePath,bool hasLowQualityImage)398 int32_t BackupFileUtils::IsFileValid(std::string &filePath, int32_t sceneCode,
399     string relativePath, bool hasLowQualityImage)
400 {
401     std::string garbledFilePath = BackupFileUtils::GarbleFilePath(filePath, sceneCode);
402     struct stat statInfo {};
403     if (stat(filePath.c_str(), &statInfo) != E_SUCCESS) {
404         bool res = false;
405         if (fileAccessHelper_ != nullptr) {
406             res = fileAccessHelper_->GetValidPath(filePath);
407         }
408         if (stat(filePath.c_str(), &statInfo) != E_SUCCESS) {
409             return hasLowQualityImage ? IsLowQualityImage(filePath, sceneCode, relativePath, hasLowQualityImage) :
410                 E_NO_SUCH_FILE;
411         }
412     }
413     if (statInfo.st_mode & S_IFDIR) {
414         MEDIA_ERR_LOG("Invalid file (%{public}s), is a directory", garbledFilePath.c_str());
415         return E_FAIL;
416     }
417     if (statInfo.st_size <= 0) {
418         MEDIA_ERR_LOG("Invalid file (%{public}s), get size (%{public}lld) <= 0", garbledFilePath.c_str(),
419             (long long)statInfo.st_size);
420         return E_FAIL;
421     }
422     return E_OK;
423 }
424 
GetFileNameFromPath(const string & path)425 string BackupFileUtils::GetFileNameFromPath(const string &path)
426 {
427     size_t pos = GetLastSlashPosFromPath(path);
428     if (pos == INVALID_RET || pos + 1 >= path.size()) {
429         MEDIA_ERR_LOG("Failed to obtain file name because pos is invalid or out of range, path: %{public}s, "
430             "size: %{public}zu, pos: %{public}zu", GarbleFilePath(path, DEFAULT_RESTORE_ID).c_str(), path.size(), pos);
431         return "";
432     }
433     return path.substr(pos + 1);
434 }
435 
GetFileTitle(const string & displayName)436 string BackupFileUtils::GetFileTitle(const string &displayName)
437 {
438     string::size_type pos = displayName.find_last_of('.');
439     return (pos == string::npos) ? displayName : displayName.substr(0, pos);
440 }
441 
GetDetailsPath(int32_t sceneCode,const std::string & type,const std::unordered_map<std::string,FailedFileInfo> & failedFiles,size_t limit)442 std::string BackupFileUtils::GetDetailsPath(int32_t sceneCode, const std::string &type,
443     const std::unordered_map<std::string, FailedFileInfo> &failedFiles, size_t limit)
444 {
445     std::string detailsPath = RESTORE_FAILED_FILES_PATH + "_" + type + ".txt";
446     if (MediaFileUtils::IsFileExists(detailsPath) && !MediaFileUtils::DeleteFile(detailsPath)) {
447         MEDIA_ERR_LOG("%{public}s exists and delete failed", detailsPath.c_str());
448         return "";
449     }
450     if (failedFiles.empty() || limit == 0) {
451         return "";
452     }
453     if (MediaFileUtils::CreateAsset(detailsPath) != E_SUCCESS) {
454         MEDIA_ERR_LOG("Create %{public}s failed", detailsPath.c_str());
455         return "";
456     }
457     std::string failedFilesStr = GetFailedFilesStr(sceneCode, failedFiles, limit);
458     if (!MediaFileUtils::WriteStrToFile(detailsPath, failedFilesStr)) {
459         MEDIA_ERR_LOG("Write to %{public}s failed", detailsPath.c_str());
460         return "";
461     }
462     return detailsPath;
463 }
464 
GetFailedFilesStr(int32_t sceneCode,const std::unordered_map<std::string,FailedFileInfo> & failedFiles,size_t limit)465 std::string BackupFileUtils::GetFailedFilesStr(int32_t sceneCode,
466     const std::unordered_map<std::string, FailedFileInfo> &failedFiles, size_t limit)
467 {
468     std::stringstream failedFilesStream;
469     failedFilesStream << "[";
470     for (const auto &iter : failedFiles) {
471         if (limit == 0) {
472             break;
473         }
474         failedFilesStream << "\n\"";
475         failedFilesStream << GetFailedFile(sceneCode, iter.first, iter.second);
476         limit > 1 ? failedFilesStream << "\"," : failedFilesStream << "\"";
477         limit--;
478     }
479     failedFilesStream << "\n]";
480     return failedFilesStream.str();
481 }
482 
CreateDataShareHelper(const sptr<IRemoteObject> & token)483 void BackupFileUtils::CreateDataShareHelper(const sptr<IRemoteObject> &token)
484 {
485     if (token != nullptr) {
486         sDataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
487         if (sDataShareHelper_ == nullptr) {
488             MEDIA_ERR_LOG("generate thumbnails after restore failed, the sDataShareHelper_ is nullptr.");
489         }
490     }
491 }
492 
GenerateThumbnailsAfterRestore()493 void BackupFileUtils::GenerateThumbnailsAfterRestore()
494 {
495     if (sDataShareHelper_ == nullptr) {
496         return;
497     }
498     std::string updateUri = PAH_GENERATE_THUMBNAILS_RESTORE;
499     MediaFileUtils::UriAppendKeyValue(updateUri, URI_PARAM_API_VERSION, to_string(MEDIA_API_VERSION_V10));
500     Uri uri(updateUri);
501     DataShare::DataSharePredicates emptyPredicates;
502     DataShare::DataShareValuesBucket valuesBucket;
503     valuesBucket.Put(MEDIA_DATA_DB_THUMBNAIL_READY, 0);
504     int result = sDataShareHelper_->Update(uri, emptyPredicates, valuesBucket);
505     if (result < 0) {
506         MEDIA_ERR_LOG("generate thumbnails after restore failed, the sDataShareHelper_ update error");
507     }
508 }
509 
GetFailedFilesList(int32_t sceneCode,const std::unordered_map<std::string,FailedFileInfo> & failedFiles,size_t limit)510 std::vector<std::string> BackupFileUtils::GetFailedFilesList(int32_t sceneCode,
511     const std::unordered_map<std::string, FailedFileInfo> &failedFiles, size_t limit)
512 {
513     std::vector<std::string> failedFilesList;
514     for (const auto &iter : failedFiles) {
515         if (limit == 0) {
516             break;
517         }
518         failedFilesList.push_back(GetFailedFile(sceneCode, iter.first, iter.second));
519         limit--;
520     }
521     return failedFilesList;
522 }
523 
GetFailedFile(int32_t sceneCode,const std::string & failedFilePath,const FailedFileInfo & failedFileInfo)524 std::string BackupFileUtils::GetFailedFile(int32_t sceneCode, const std::string &failedFilePath,
525     const FailedFileInfo &failedFileInfo)
526 {
527     MEDIA_ERR_LOG("Failed file: %{public}s, %{public}s, %{public}s, %{public}s",
528         GarbleFilePath(failedFilePath, sceneCode).c_str(), failedFileInfo.albumName.c_str(),
529         GarbleFileName(failedFileInfo.displayName).c_str(), failedFileInfo.errorCode.c_str());
530     // format: albumName/displayName
531     return failedFileInfo.albumName + "/" + failedFileInfo.displayName;
532 }
533 
GetPathPosByPrefixLevel(int32_t sceneCode,const std::string & path,int32_t prefixLevel,size_t & pos)534 bool BackupFileUtils::GetPathPosByPrefixLevel(int32_t sceneCode, const std::string &path, int32_t prefixLevel,
535     size_t &pos)
536 {
537     int32_t count = 0;
538     for (size_t index = 0; index < path.length(); index++) {
539         if (path[index] != '/') {
540             continue;
541         }
542         count++;
543         if (count == prefixLevel) {
544             pos = index;
545             break;
546         }
547     }
548     if (count < prefixLevel) {
549         MEDIA_ERR_LOG("Get position failed for %{public}s, %{public}d < %{public}d",
550             GarbleFilePath(path, sceneCode).c_str(), count, prefixLevel);
551         return false;
552     }
553     return true;
554 }
555 
ShouldIncludeSd(const std::string & prefix)556 bool BackupFileUtils::ShouldIncludeSd(const std::string &prefix)
557 {
558     return MediaFileUtils::IsFileExists(prefix + "/" + PHOTO_SD_DB_NAME) ||
559         MediaFileUtils::IsFileExists(prefix + "/" + VIDEO_SD_DB_NAME);
560 }
561 
DeleteSdDatabase(const std::string & prefix)562 void BackupFileUtils::DeleteSdDatabase(const std::string &prefix)
563 {
564     std::vector<std::string> sdDbs = { PHOTO_SD_DB_NAME, VIDEO_SD_DB_NAME };
565     for (const auto &sdDb : sdDbs) {
566         std::string sdDbPath = prefix + "/" + sdDb;
567         if (!MediaFileUtils::IsFileExists(sdDbPath)) {
568             continue;
569         }
570         if (!MediaFileUtils::DeleteFile(sdDbPath)) {
571             MEDIA_ERR_LOG("Delete Sd database %{public}s failed, errno: %{public}d", sdDb.c_str(), errno);
572         }
573     }
574 }
575 
IsLivePhoto(const FileInfo & fileInfo)576 bool BackupFileUtils::IsLivePhoto(const FileInfo &fileInfo)
577 {
578     return fileInfo.specialFileType == LIVE_PHOTO_TYPE || fileInfo.specialFileType == LIVE_PHOTO_HDR_TYPE;
579 }
580 
addPathSuffix(const string & oldPath,const string & suffix,string & newPath)581 static void addPathSuffix(const string &oldPath, const string &suffix, string &newPath)
582 {
583     if (oldPath.empty() || suffix.empty()) {
584         MEDIA_WARN_LOG("oldPath or suffix is empty");
585         return;
586     }
587 
588     newPath = oldPath + suffix;
589     while (MediaFileUtils::IsFileExists(newPath)) {
590         newPath += ".dup" + suffix;
591     }
592 }
593 
ConvertToMovingPhoto(FileInfo & fileInfo)594 bool BackupFileUtils::ConvertToMovingPhoto(FileInfo &fileInfo)
595 {
596     if (!MediaFileUtils::IsFileExists(fileInfo.filePath)) {
597         MEDIA_ERR_LOG("Live photo does not exist, path: %{private}s, errno: %{public}d",
598             fileInfo.filePath.c_str(), errno);
599         return false;
600     }
601 
602     string movingPhotoImagePath;
603     addPathSuffix(fileInfo.filePath, ".jpg", movingPhotoImagePath);
604     addPathSuffix(fileInfo.filePath, ".mp4", fileInfo.movingPhotoVideoPath);
605     addPathSuffix(fileInfo.filePath, ".extra", fileInfo.extraDataPath);
606     int32_t ret = MovingPhotoFileUtils::ConvertToMovingPhoto(
607         fileInfo.filePath, movingPhotoImagePath, fileInfo.movingPhotoVideoPath, fileInfo.extraDataPath);
608     if (ret != E_OK) {
609         return false;
610     }
611 
612     if (!MediaFileUtils::DeleteFile(fileInfo.filePath)) {
613         MEDIA_WARN_LOG("Failed to delete original live photo: %{private}s, errno: %{public}d",
614             fileInfo.filePath.c_str(), errno);
615     }
616     fileInfo.filePath = movingPhotoImagePath;
617     return true;
618 }
619 
GetLastSlashPosFromPath(const std::string & path)620 size_t BackupFileUtils::GetLastSlashPosFromPath(const std::string &path)
621 {
622     if (path.empty()) {
623         MEDIA_ERR_LOG("Failed to obtain last slash pos because given path is empty");
624         return INVALID_RET;
625     }
626     size_t pos = path.rfind("/");
627     if (pos == std::string::npos) {
628         MEDIA_ERR_LOG("Failed to obtain last slash pos because / not found");
629         return INVALID_RET;
630     }
631     return pos;
632 }
633 
GetFileFolderFromPath(const std::string & path,bool shouldStartWithSlash)634 std::string BackupFileUtils::GetFileFolderFromPath(const std::string &path, bool shouldStartWithSlash)
635 {
636     size_t endPos = GetLastSlashPosFromPath(path);
637     if (endPos == INVALID_RET) {
638         MEDIA_ERR_LOG("Failed to obtain file folder, path: %{public}s",
639             GarbleFilePath(path, DEFAULT_RESTORE_ID).c_str());
640         return "";
641     }
642     size_t startPos = MediaFileUtils::StartsWith(path, "/") && !shouldStartWithSlash ? 1 : 0;
643     if (startPos >= endPos) {
644         MEDIA_ERR_LOG("Failed to obtain file folder because start %{public}zu >= end %{public}zu, path: %{public}s",
645             startPos, endPos, GarbleFilePath(path, DEFAULT_RESTORE_ID).c_str());
646         return "";
647     }
648     return path.substr(startPos, endPos - startPos);
649 }
650 
GetExtraPrefixForRealPath(int32_t sceneCode,const std::string & path)651 std::string BackupFileUtils::GetExtraPrefixForRealPath(int32_t sceneCode, const std::string &path)
652 {
653     return sceneCode == UPGRADE_RESTORE_ID && IsAppTwinData(path) ? APP_TWIN_DATA_PREFIX : "";
654 }
655 
IsAppTwinData(const std::string & path)656 bool BackupFileUtils::IsAppTwinData(const std::string &path)
657 {
658     int32_t userId = GetUserId(path);
659     return userId >= APP_TWIN_DATA_START && userId <= APP_TWIN_DATA_END;
660 }
661 
GetUserId(const std::string & path)662 int32_t BackupFileUtils::GetUserId(const std::string &path)
663 {
664     int32_t userId = -1;
665      if (!MediaFileUtils::StartsWith(path, INTERNAL_PREFIX)) {
666         return userId;
667     }
668     std::string tmpPath = path.substr(INTERNAL_PREFIX.size());
669     if (tmpPath.empty()) {
670         MEDIA_ERR_LOG("Get substr failed, path: %{public}s", path.c_str());
671         return userId;
672     }
673     size_t posStart = tmpPath.find_first_of("/");
674     if (posStart == std::string::npos) {
675         MEDIA_ERR_LOG("Get first / failed, path: %{public}s", path.c_str());
676         return userId;
677     }
678     size_t posEnd = tmpPath.find_first_of("/", posStart + 1);
679     if (posEnd == std::string::npos) {
680         MEDIA_ERR_LOG("Get second / failed, path: %{public}s", path.c_str());
681         return userId;
682     }
683     std::string userIdStr = tmpPath.substr(posStart + 1, posEnd - posStart -1);
684     if (userIdStr.empty() || !MediaLibraryDataManagerUtils::IsNumber(userIdStr)) {
685         MEDIA_ERR_LOG("Get userId failed, empty or not number, path: %{public}s", path.c_str());
686         return userId;
687     }
688     return std::atoi(userIdStr.c_str());
689 }
690 } // namespace Media
691 } // namespace OHOS