• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 #define MLOG_TAG "FileUtils"
16 
17 #include "media_file_utils.h"
18 
19 #include <algorithm>
20 #include <stack>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <filesystem>
24 #include <fstream>
25 #include <ftw.h>
26 #include <regex>
27 #include <securec.h>
28 #include <sstream>
29 #include <sys/sendfile.h>
30 #include <sys/stat.h>
31 #include <sys/statvfs.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include <unordered_map>
35 #include <utime.h>
36 
37 #include "avmetadatahelper.h"
38 #include "directory_ex.h"
39 #include "hmdfs.h"
40 #include "ipc_skeleton.h"
41 #include "media_column.h"
42 #include "media_file_uri.h"
43 #include "media_log.h"
44 #include "medialibrary_db_const.h"
45 #include "medialibrary_errno.h"
46 #include "medialibrary_type_const.h"
47 #include "mimetype_utils.h"
48 #include "medialibrary_tracer.h"
49 #include "ptp_medialibrary_manager_uri.h"
50 #include "string_ex.h"
51 #include "userfilemgr_uri.h"
52 #include "data_secondary_directory_uri.h"
53 #include "image_source.h"
54 #include "image_packer.h"
55 
56 using namespace std;
57 
58 namespace OHOS::Media {
59 static const mode_t CHOWN_RWX_USR_GRP = 02771;
60 static const mode_t CHOWN_RW_USR_GRP = 0660;
61 static const mode_t CHOWN_RO_USR_GRP = 0644;
62 constexpr size_t DISPLAYNAME_MAX = 255;
63 const int32_t OPEN_FDS = 64;
64 const std::string PATH_PARA = "path=";
65 constexpr unsigned short MAX_RECURSION_DEPTH = 4;
66 constexpr size_t DEFAULT_TIME_SIZE = 32;
67 constexpr int32_t CROSS_POLICY_ERR = 18;
68 const int32_t HMFS_MONITOR_FL = 2;
69 const int32_t INTEGER_MAX_LENGTH = 10;
70 const std::string LISTENING_BASE_PATH = "/storage/media/local/files/";
71 const std::string PHOTO_DIR = "Photo";
72 const std::string AUDIO_DIR = "Audio";
73 const std::string THUMBS_DIR = ".thumbs";
74 const std::string EDIT_DATA_DIR = ".editData";
75 const std::string THUMBS_PHOTO_DIR = ".thumbs/Photo";
76 const std::string EDIT_DATA_PHOTO_DIR = ".editData/Photo";
77 const std::string CLOUD_FILE_PATH = "/storage/cloud/files";
78 const std::string TMP_SUFFIX = "tmp";
79 const std::vector<std::string> SET_LISTEN_DIR = {
80     PHOTO_DIR, AUDIO_DIR, THUMBS_DIR, EDIT_DATA_DIR, THUMBS_PHOTO_DIR, EDIT_DATA_PHOTO_DIR
81 };
82 const std::string KVSTORE_FILE_ID_TEMPLATE = "0000000000";
83 const std::string KVSTORE_DATE_KEY_TEMPLATE = "0000000000000";
84 const std::string MAX_INTEGER = "2147483648";
85 const std::string DEFAULT_IMAGE_NAME = "IMG_";
86 const std::string DEFAULT_VIDEO_NAME = "VID_";
87 const std::string DEFAULT_AUDIO_NAME = "AUD_";
88 const int64_t UNIT = 1000;
89 const int64_t STD_UNIT = 1024;
90 const int64_t THRESHOLD = 512;
91 const std::string DATA_PATH = "/data/storage/el2/base";
92 #define HMFS_IOCTL_HW_GET_FLAGS _IOR(0XF5, 70, unsigned int)
93 #define HMFS_IOCTL_HW_SET_FLAGS _IOR(0XF5, 71, unsigned int)
94 const std::string MEDIA_DATA_DEVICE_PATH = "local";
95 
96 static const std::unordered_map<std::string, std::vector<std::string>> MEDIA_MIME_TYPE_MAP = {
97     { "application/epub+zip", { "epub" } },
98     { "application/lrc", { "lrc"} },
99     { "application/pkix-cert", { "cer" } },
100     { "application/rss+xml", { "rss" } },
101     { "application/sdp", { "sdp" } },
102     { "application/smil+xml", { "smil" } },
103     { "application/ttml+xml", { "ttml", "dfxp" } },
104     { "application/vnd.ms-pki.stl", { "stl" } },
105     { "application/vnd.ms-powerpoint", { "pot", "ppt" } },
106     { "application/vnd.ms-wpl", { "wpl" } },
107     { "application/vnd.stardivision.writer", { "vor" } },
108     { "application/vnd.youtube.yt", { "yt" } },
109     { "application/x-font", { "pcf" } },
110     { "application/x-mobipocket-ebook", { "prc", "mobi" } },
111     { "application/x-pem-file", { "pem" } },
112     { "application/x-pkcs12", { "p12", "pfx" } },
113     { "application/x-subrip", { "srt" } },
114     { "application/x-webarchive", { "webarchive" } },
115     { "application/x-webarchive-xml", { "webarchivexml" } },
116     { "application/pgp-signature", { "pgp" } },
117     { "application/x-x509-ca-cert", { "crt", "der" } },
118     { "application/json", { "json" } },
119     { "application/javascript", { "js" } },
120     { "application/zip", { "zip" } },
121     { "application/rar", { "rar" } },
122     { "application/pdf", { "pdf" } },
123     { "application/msword", { "doc" } },
124     { "application/ms-excel", { "xls" } },
125     { "application/vnd.openxmlformats-officedocument.wordprocessingml.document", { "docx" } },
126     { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", { "xlsx" } },
127     { "application/vnd.openxmlformats-officedocument.presentationml.presentation", { "pptx" } },
128     { "audio/3gpp", { "3ga" } },
129     { "audio/ac3", { "ac3", "a52"} },
130     { "audio/amr", { "amr" } },
131     { "audio/imelody", { "imy" } },
132     { "audio/midi", { "rtttl", "xmf", "rtx" } },
133     { "audio/mobile-xmf", { "mxmf"} },
134     { "audio/mp4", { "m4a", "m4b", "m4p", "f4a", "f4b", "f4p" } },
135     { "audio/mpegurl", { "m3u" } },
136     { "audio/sp-midi", { "smf" } },
137     { "audio/x-matroska", { "mka" } },
138     { "audio/x-pn-realaudio", { "ra" } },
139     { "audio/x-mpeg", { "mp3" } },
140     { "audio/aac", { "aac", "adts", "adt" } },
141     { "audio/basic", { "snd" } },
142     { "audio/flac", { "flac" } },
143     { "audio/mpeg", { "mp3", "mp2", "mp1", "mpa", "m4r" } },
144     { "audio/wav", { "wav" } },
145     { "audio/ogg", { "ogg" } },
146     { "image/gif", { "gif"} },
147     { "image/heic", { "heic" } },
148     { "image/heic-sequence", { "heics", "heifs" } },
149     { "image/bmp", { "bmp", "bm" } },
150     { "image/heif", { "heif", "hif" } },
151     { "image/avif", { "avif" } },
152     { "image/ico", { "cur" } },
153     { "image/webp", { "webp"} },
154     { "image/x-adobe-dng", { "dng" } },
155     { "image/x-fuji-raf", { "raf" } },
156     { "image/x-icon", { "ico" } },
157     { "image/x-nikon-nrw", { "nrw" } },
158     { "image/x-panasonic-rw2", { "rw2" } },
159     { "image/x-pentax-pef", { "pef" } },
160     { "image/x-samsung-srw", { "srw" } },
161     { "image/x-sony-arw", { "arw" } },
162     { "image/jpeg", { "jpg", "jpeg", "jpe" } },
163     { "image/png", { "png" } },
164     { "image/svg+xml", { "svg", "svgz" } },
165     { "image/x-dcraw", { "raw" } },
166     { "image/ief", { "ief" } },
167     { "image/jp2", { "jp2", "jpg2" } },
168     { "image/ipm", { "ipm" } },
169     { "image/jpm", { "jpm" } },
170     { "image/ipx", { "jpx", "jpf" } },
171     { "image/pcx", { "pcx" } },
172     { "image/tiff", { "tiff", "tif" } },
173     { "image/vnd.divu", { "djvu", "djv" } },
174     { "image/vnd.wap.wbmp", { "wbmp" } },
175     { "image/x-canon-cr2", { "cr2" } },
176     { "image/x-canon-crw", { "crw" } },
177     { "image/x-cmu-raster", { "ras" } },
178     { "image/x-coreldraw", { "cdr" } },
179     { "image/x-coreldrawpattern", { "pat" } },
180     { "image/x-coreldrawtemplate", { "cdt" } },
181     { "image/x-corelphotopaint", { "cpt" } },
182     { "image/x-epson-erf", { "erf" } },
183     { "image/x-jg", { "art" } },
184     { "image/x-jng", { "jng" } },
185     { "image/x-nikon-nef", { "nef" } },
186     { "image/x-olvmpus-orf", { "orf" } },
187     { "image/x-photoshop", { "psd" } },
188     { "image/x-portable-anymap", { "pnm" } },
189     { "image/x-portable-bitmap", { "pbm" } },
190     { "image/x-portable-graymap", { "pgm" } },
191     { "image/x-portable-pixmap", { "ppm" } },
192     { "image/x-rgb", { "rgb" } },
193     { "image/x-xbitmap", { "xbm" } },
194     { "image/x-xpixmap", { "xpm" } },
195     { "image/x-xwindowdump", { "xwd" } },
196     { "video/3gpp2", { "3gpp2", "3gp2", "3g2" } },
197     { "video/3gpp", { "3gpp", "3gp" } },
198     { "video/mp4", { "m4v", "f4v", "mp4v", "mpeg4", "mp4" } },
199     { "video/mp2t", { "m2ts", "mts"} },
200     { "video/mp2ts", { "ts" } },
201     { "video/vnd.youtube.yt", { "yt" } },
202     { "video/x-webex", { "wrf" } },
203     { "video/mpeg", { "mpe", "mpeg", "mpeg2", "mpv2", "mp2v", "m2v", "m2t", "mpeg1", "mpv1", "mp1v", "m1v", "mpg" } },
204     { "video/quicktime", { "mov", "qt" } },
205     { "video/x-matroska", { "mkv", "mpv" } },
206     { "video/webm", { "webm" } },
207     { "video/H264", { "h264" } },
208     { "video/x-flv", { "flv" } },
209     { "video/avi", { "avi" } },
210     { "video/x-pn-realvideo", { "rmvb" } },
211     { "video/annodex", { "axv" } },
212     { "video/dl", { "dl" } },
213     { "video/dv", { "dif", "dv" } },
214     { "video/fli", { "fli" } },
215     { "video/gl", { "gl" } },
216     { "video/ogg", { "ogv" } },
217     { "video/vnd.mpegurl", { "mxu" } },
218     { "video/x-la-asf", { "lsf",  "lsx" } },
219     { "video/x-mng", { "mng" } },
220     { "video/x-ms-asf", { "asf", "asx" } },
221     { "video/x-ms-wm", { "wm" } },
222     { "video/x-ms-wmv", { "wmv" } },
223     { "video/x-ms-wmx", { "wmx" } },
224     { "video/x-ms-wvx", { "wvx" } },
225     { "video/x-sgi-movie", { "movie" } },
226     { "text/comma-separated-values", { "csv" } },
227     { "text/plain", { "diff", "po", "txt" } },
228     { "text/rtf", { "rtf" } },
229     { "text/text", { "phps", "m3u", "m3u8" } },
230     { "text/xml", { "xml" } },
231     { "text/x-vcard", { "vcf" } },
232     { "text/x-c++hdr", { "hpp", "h++", "hxx", "hh" } },
233     { "text/x-c++src", { "cpp", "c++", "cxx", "cc" } },
234     { "text/css", { "css" } },
235     { "text/html", { "html", "htm", "shtml"} },
236     { "text/markdown", { "md", "markdown" } },
237     { "text/x-java", { "java" } },
238     { "text/x-python", { "py" } }
239 };
240 
241 static const std::unordered_map<std::string, std::vector<std::string>> MEDIA_EXTRA_MIME_TYPE_MAP = {
242     { "audio/3gpp", { "3gpp" } },
243     { "audio/midi", { "mid", "midi", "kar" } },
244     { "audio/basic", { "au" } },
245     { "audio/x-pn-realaudio", { "rm", "ram" } },
246     { "audio/aac-adts", { "aac" } },
247     { "audio/mpeg", { "m4a", "mpga", "mpega" } },
248     { "audio/x-mpegurl", { "m3u", "m3u8" } },
249     { "audio/ffmpeg", { "ape" } },
250     { "audio/mp4", { "isma" } },
251     { "audio/ac4", { "ac4" } },
252     { "audio/amr-wb", { "awb" } },
253     { "audio/annodex", { "axa" } },
254     { "audio/csound", { "csd", "orc", "sco" } },
255     { "audio/ogg", { "oga", "ogg", "opus", "spx" } },
256     { "audio/prs.sid", { "sid" } },
257     { "audio/x-aiff", { "aif", "aiff", "aifc" } },
258     { "audio/x-gsm", { "gsm"} },
259     { "audio/x-mpegurl", { "m3u" } },
260     { "audio/x-ms-wma", { "wma" } },
261     { "audio/x-ms-wax", { "wax" } },
262     { "audio/x-realaudio", { "ra" } },
263     { "audio/x-scpls", { "pls" } },
264     { "audio/x-sd2", { "sd2" } },
265     { "audio/x-wav", { "wav" } }
266 };
267 
GetAllTypes(const int32_t extension)268 vector<string> MediaFileUtils::GetAllTypes(const int32_t extension)
269 {
270     vector<std::string> allTypesVec;
271     if (extension != MEDIA_TYPE_IMAGE && extension != MEDIA_TYPE_VIDEO) {
272         return allTypesVec;
273     }
274     for (auto &item : MEDIA_MIME_TYPE_MAP) {
275         if (extension == MimeTypeUtils::GetMediaTypeFromMimeType(item.first)) {
276             for (auto &ext : item.second) {
277                 allTypesVec.push_back(ext);
278             }
279         }
280     }
281     return allTypesVec;
282 }
283 
UnlinkCb(const char * fpath,const struct stat * sb,int32_t typeflag,struct FTW * ftwbuf)284 int32_t UnlinkCb(const char *fpath, const struct stat *sb, int32_t typeflag, struct FTW *ftwbuf)
285 {
286     CHECK_AND_RETURN_RET_LOG(fpath != nullptr, E_FAIL, "fpath == nullptr");
287     int32_t errRet = remove(fpath);
288     CHECK_AND_PRINT_LOG(!errRet, "Failed to remove errno: %{public}d, path: %{private}s", errno, fpath);
289     return errRet;
290 }
291 
RemoveDirectory(const string & path)292 int32_t MediaFileUtils::RemoveDirectory(const string &path)
293 {
294     return nftw(path.c_str(), UnlinkCb, OPEN_FDS, FTW_DEPTH | FTW_PHYS);
295 }
296 
DesensitizePath(const std::string & path)297 std::string MediaFileUtils::DesensitizePath(const std::string &path)
298 {
299     string result = path;
300     CHECK_AND_RETURN_RET(result.length() > CLOUD_FILE_PATH.length(), result);
301     return result.replace(0, CLOUD_FILE_PATH.length(), "*");
302 }
303 
PrintStatInformation(const std::string & path)304 void MediaFileUtils::PrintStatInformation(const std::string& path)
305 {
306     struct stat statInfo {};
307     if ((stat(path.c_str(), &statInfo)) == E_SUCCESS) {
308         MEDIA_INFO_LOG("path:%{public}s uid:%{public}d, gid:%{public}d, mode:%{public}d",
309             DesensitizePath(path).c_str(), statInfo.st_uid, statInfo.st_gid, statInfo.st_mode);
310     } else {
311         MEDIA_INFO_LOG("path:%{public}s is not exist", DesensitizePath(path).c_str());
312     }
313 }
314 
Mkdir(const string & subStr,shared_ptr<int> errCodePtr)315 bool MediaFileUtils::Mkdir(const string &subStr, shared_ptr<int> errCodePtr)
316 {
317     mode_t mask = umask(0);
318     if (mkdir(subStr.c_str(), CHOWN_RWX_USR_GRP) == -1) {
319         if (errCodePtr != nullptr) {
320             *errCodePtr = errno;
321         }
322         int err = errno;
323         MEDIA_ERR_LOG("Failed to create directory %{public}d, path:%{public}s", err, DesensitizePath(subStr).c_str());
324         if (err == EACCES) {
325             PrintStatInformation(GetParentPath(subStr));
326         }
327         umask(mask);
328         return (err == EEXIST) ? true : false;
329     }
330     umask(mask);
331     return true;
332 }
333 
CreateDirectory(const string & dirPath,shared_ptr<int> errCodePtr)334 bool MediaFileUtils::CreateDirectory(const string &dirPath, shared_ptr<int> errCodePtr)
335 {
336     string subStr;
337     string segment;
338 
339     /*  Create directory and its sub directories if does not exist
340      *  take each string after '/' create directory if does not exist.
341      *  Created directory will be the base path for the next sub directory.
342      */
343 
344     stringstream folderStream(dirPath);
345     while (getline(folderStream, segment, '/')) {
346         if (segment.empty()) {    // skip the first "/" in case of "/storage/cloud/files"
347             continue;
348         }
349 
350         subStr.append(SLASH_CHAR + segment);
351         if (!IsDirectory(subStr, errCodePtr)) {
352             CHECK_AND_RETURN_RET(Mkdir(subStr, errCodePtr), false);
353         }
354     }
355 
356     return true;
357 }
358 
IsFileExists(const string & fileName)359 bool MediaFileUtils::IsFileExists(const string &fileName)
360 {
361     struct stat statInfo {};
362 
363     return ((stat(fileName.c_str(), &statInfo)) == E_SUCCESS);
364 }
365 
IsFileValid(const string & fileName)366 bool MediaFileUtils::IsFileValid(const string &fileName)
367 {
368     struct stat statInfo {};
369     if (!fileName.empty()) {
370         if (stat(fileName.c_str(), &statInfo) == E_SUCCESS) {
371             // if the given path is a directory path, return
372             CHECK_AND_RETURN_RET_LOG(!(statInfo.st_mode & S_IFDIR), false, "file is a directory");
373 
374             // if the file is empty
375             CHECK_AND_WARN_LOG(statInfo.st_size != 0, "file is empty");
376             return true;
377         }
378     }
379     return false;
380 }
381 
IsDirEmpty(const string & path)382 bool MediaFileUtils::IsDirEmpty(const string &path)
383 {
384     DIR *dir = opendir(path.c_str());
385     if (dir == nullptr) {
386         MEDIA_ERR_LOG("Failed to open dir:%{private}s, errno: %{public}d. Just return dir NOT empty.",
387             path.c_str(), errno);
388         return false;
389     }
390     bool ret = true;
391     struct dirent *entry;
392     while ((entry = readdir(dir)) != nullptr) {
393         if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
394             ret = false;
395             break;
396         }
397     }
398     if (closedir(dir) < 0) {
399         MEDIA_ERR_LOG("Fail to closedir: %{private}s, errno: %{public}d.", path.c_str(), errno);
400     }
401     return ret;
402 }
403 
GetFileName(const string & filePath)404 string MediaFileUtils::GetFileName(const string &filePath)
405 {
406     string fileName;
407 
408     if (!(filePath.empty())) {
409         size_t lastSlash = filePath.rfind('/');
410         if (lastSlash != string::npos) {
411             if (filePath.size() > (lastSlash + 1)) {
412                 fileName = filePath.substr(lastSlash + 1);
413             }
414         }
415     }
416 
417     return fileName;
418 }
419 
CreateAssetRealName(int32_t fileId,int32_t mediaType,const string & extension,string & name)420 int32_t MediaFileUtils::CreateAssetRealName(int32_t fileId, int32_t mediaType,
421     const string &extension, string &name)
422 {
423     const int32_t maxComplementAssetId = 999;
424     string fileNumStr = to_string(fileId);
425     if (fileId <= maxComplementAssetId) {
426         size_t fileIdLen = fileNumStr.length();
427         fileNumStr = ("00" + fileNumStr).substr(fileIdLen - 1);
428     }
429 
430     string mediaTypeStr;
431     switch (mediaType) {
432         case MediaType::MEDIA_TYPE_IMAGE:
433             mediaTypeStr = DEFAULT_IMAGE_NAME;
434             break;
435         case MediaType::MEDIA_TYPE_VIDEO:
436             mediaTypeStr = DEFAULT_VIDEO_NAME;
437             break;
438         case MediaType::MEDIA_TYPE_AUDIO:
439             mediaTypeStr = DEFAULT_AUDIO_NAME;
440             break;
441         default:
442             MEDIA_ERR_LOG("This mediatype %{public}d can not get real name", mediaType);
443             return E_INVALID_VALUES;
444     }
445 
446     static const int32_t CONFLICT_TIME = 100;
447     if (extension.length() == 0) {
448         name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" + fileNumStr;
449     } else {
450         name = mediaTypeStr + to_string(MediaFileUtils::UTCTimeSeconds() + CONFLICT_TIME) + "_" +
451            fileNumStr + "." + extension;
452     }
453     return E_OK;
454 }
455 
IsDirectory(const string & dirName,shared_ptr<int> errCodePtr)456 bool MediaFileUtils::IsDirectory(const string &dirName, shared_ptr<int> errCodePtr)
457 {
458     struct stat statInfo {};
459 
460     int32_t ret = stat(dirName.c_str(), &statInfo);
461     if (ret == E_SUCCESS) {
462         if (statInfo.st_mode & S_IFDIR) {
463             return true;
464         }
465     } else if (errCodePtr != nullptr) {
466         *errCodePtr = errno;
467         MEDIA_ERR_LOG("ret: %{public}d, errno: %{public}d", ret, errno);
468         return false;
469     }
470     MEDIA_ERR_LOG("ret: %{public}d, errno: %{public}d", ret, errno);
471     return false;
472 }
473 
CreateFile(const string & filePath)474 bool MediaFileUtils::CreateFile(const string &filePath)
475 {
476     bool state = false;
477 
478     if (filePath.empty()) {
479         MEDIA_ERR_LOG("Invalid file path");
480         return state;
481     }
482     if (IsFileExists(filePath)) {
483         MEDIA_ERR_LOG("file already exists");
484         return state;
485     }
486 
487     ofstream file(filePath);
488     if (!file) {
489         MEDIA_ERR_LOG("Output file path could not be created");
490         return state;
491     }
492 
493     if (chmod(filePath.c_str(), CHOWN_RW_USR_GRP) == E_SUCCESS) {
494         state = true;
495     } else {
496         MEDIA_ERR_LOG("Failed to change permissions, error: %{public}d", errno);
497     }
498 
499     file.close();
500 
501     return state;
502 }
503 
DeleteFile(const string & fileName)504 bool MediaFileUtils::DeleteFile(const string &fileName)
505 {
506     return (remove(fileName.c_str()) == E_SUCCESS);
507 }
508 
DeleteFileWithRetry(const string & fileName)509 bool MediaFileUtils::DeleteFileWithRetry(const string &fileName)
510 {
511     int32_t maxRetryCount = 3;
512     int32_t retryCount = 0;
513     bool isRemoved = false;
514     bool isExists = false;
515     bool isDeleted = false;
516     while (!isDeleted && retryCount < maxRetryCount) {
517         retryCount++;
518         isRemoved = DeleteFile(fileName);
519         isExists = IsFileExists(fileName);
520         isDeleted = isRemoved && !isExists;
521         CHECK_AND_PRINT_LOG(isDeleted,
522             "DeleteFileWithRetry fail, retryCount: %{public}d, "
523             "isRemoved: %{public}d, isExists: %{public}d, fileName: %{public}s",
524             retryCount,
525             isRemoved,
526             isExists,
527             fileName.c_str());
528     }
529     return isDeleted;
530 }
531 
DeleteDir(const string & dirName)532 bool MediaFileUtils::DeleteDir(const string &dirName)
533 {
534     bool errRet = false;
535 
536     if (IsDirectory(dirName)) {
537         errRet = (RemoveDirectory(dirName) == E_SUCCESS);
538     }
539 
540     return errRet;
541 }
542 
CopyFileAndDelSrc(const std::string & srcFile,const std::string & destFile)543 bool MediaFileUtils::CopyFileAndDelSrc(const std::string &srcFile, const std::string &destFile)
544 {
545     bool fileExist = IsFileExists(destFile);
546     if (fileExist) {
547         MEDIA_INFO_LOG("destFile:%{private}s already exists", destFile.c_str());
548         CHECK_AND_RETURN_RET_LOG(CopyFileUtil(destFile, destFile + TMP_SUFFIX), false,
549             "copy destfile:%{private}s failed", destFile.c_str());
550         CHECK_AND_RETURN_RET_LOG(DeleteFile(destFile), false, "delete destFile:%{private}s error", destFile.c_str());
551     }
552 
553     if (CopyFileUtil(srcFile, destFile)) {
554         CHECK_AND_PRINT_LOG(DeleteFile(srcFile), "delete srcFile:%{private}s failed", srcFile.c_str());
555         CHECK_AND_PRINT_LOG(DeleteFile(destFile + TMP_SUFFIX), "delete tmpFile:%{private}s failed", srcFile.c_str());
556         return true;
557     }
558 
559     if (fileExist) {
560         CHECK_AND_PRINT_LOG(CopyFileUtil(destFile + TMP_SUFFIX, destFile),
561             "recover destFile:%{private}s error", destFile.c_str());
562         CHECK_AND_PRINT_LOG(DeleteFile(destFile + TMP_SUFFIX), "delete tmpFile:%{private}s failed", srcFile.c_str());
563     } else {
564         bool delDestFileRet = DeleteFile(destFile);
565         MEDIA_ERR_LOG("copy srcFile:%{private}s failed,delDestFileRet:%{public}d", srcFile.c_str(), delDestFileRet);
566     }
567     return false;
568 }
569 
570 /**
571  * @brief Copy the contents of srcPath to destPath, delete the successfully copied files and directories.
572  *
573  * @param srcPath must be a directory.
574  * @param destPath must be a directory.
575  * @param curRecursionDepth current recursion depth. The maximum value is {@code MAX_RECURSION_DEPTH}.
576  * @return true: all contents of {@code srcPath} are successfully copied to {@code destPath}.
577  *         false: as long as there is one item of {@code srcPath} is not successfully copied to {@code destPath}.
578  */
CopyDirAndDelSrc(const std::string & srcPath,const std::string & destPath,unsigned short curRecursionDepth)579 bool MediaFileUtils::CopyDirAndDelSrc(const std::string &srcPath, const std::string &destPath,
580     unsigned short curRecursionDepth)
581 {
582     CHECK_AND_RETURN_RET_LOG(curRecursionDepth <= MAX_RECURSION_DEPTH, false,
583         "curRecursionDepth:%{public}d>MAX_RECURSION_DEPTH", curRecursionDepth);
584     ++curRecursionDepth;
585     bool ret = true;
586     DIR* srcDir = opendir(srcPath.c_str());
587     CHECK_AND_RETURN_RET_LOG(srcDir != nullptr, false,
588         "open srcDir:%{private}s failed,errno:%{public}d", srcPath.c_str(), errno);
589 
590     if (!IsFileExists(destPath)) {
591         if (!CreateDirectory(destPath)) {
592             MEDIA_ERR_LOG("create destPath:%{private}s failed", srcPath.c_str());
593             closedir(srcDir);
594             return false;
595         }
596     }
597     struct dirent* entry;
598     while ((entry = readdir(srcDir))!= nullptr) {
599         bool cond = (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0);
600         CHECK_AND_CONTINUE(!cond);
601         string srcSubPath = srcPath + SLASH_STR + (entry->d_name);
602         string destSubPath = destPath + SLASH_STR + (entry->d_name);
603         if (entry->d_type == DT_DIR) {
604             ret = CopyDirAndDelSrc(srcSubPath, destSubPath, curRecursionDepth) && ret;
605             continue;
606         }
607         if (entry->d_type == DT_REG) {
608             ret = CopyFileAndDelSrc(srcSubPath, destSubPath) && ret;
609         } else {
610             MEDIA_ERR_LOG("unknown file type,srcSubPath:%{private}s", srcSubPath.c_str());
611             ret = false;
612         }
613     }
614 
615     closedir(srcDir);
616     MEDIA_INFO_LOG("srcPath:%{private}s,destPath:%{private}s,coypPathAndDelSrcRet:%{public}d",
617         srcPath.c_str(), destPath.c_str(), ret);
618     return ret;
619 }
620 
BackupPhotoDir()621 void MediaFileUtils::BackupPhotoDir()
622 {
623     string dirPath = ROOT_MEDIA_DIR + PHOTO_BUCKET;
624     // check whether dir empty
625     if (!IsDirEmpty(dirPath)) {
626         MEDIA_INFO_LOG("backup for: %{private}s", dirPath.c_str());
627         string suffixName = dirPath.substr(ROOT_MEDIA_DIR.length());
628         CreateDirectory(ROOT_MEDIA_DIR + MEDIALIBRARY_TEMP_DIR);
629         CopyDirAndDelSrc(dirPath, ROOT_MEDIA_DIR + MEDIALIBRARY_TEMP_DIR + SLASH_STR + suffixName);
630     }
631 }
632 
RecoverMediaTempDir()633 void MediaFileUtils::RecoverMediaTempDir()
634 {
635     string recoverPath = ROOT_MEDIA_DIR + MEDIALIBRARY_TEMP_DIR + SLASH_STR + PHOTO_BUCKET;
636     if (!IsDirEmpty(recoverPath)) {
637         DIR *dir = opendir((recoverPath).c_str());
638         if (dir == nullptr) {
639             MEDIA_ERR_LOG("Error opening temp directory, errno: %{public}d", errno);
640             return;
641         }
642 
643         struct dirent *entry;
644         while ((entry = readdir(dir)) != nullptr) {
645             // filter . && .. dir
646             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
647                 continue;
648             }
649             std::string fullPath = recoverPath + SLASH_STR + entry->d_name;
650             struct stat fileStat;
651             if (stat(fullPath.c_str(), &fileStat) == -1) {
652                 closedir(dir);
653                 return;
654             }
655             string suffixName = fullPath.substr((recoverPath).length());
656             CopyDirAndDelSrc(fullPath, ROOT_MEDIA_DIR + PHOTO_BUCKET + suffixName);
657         }
658         DeleteDir(ROOT_MEDIA_DIR + MEDIALIBRARY_TEMP_DIR);
659         closedir(dir);
660     }
661 }
662 
MoveFile(const string & oldPath,const string & newPath,bool isSupportCrossPolicy)663 bool MediaFileUtils::MoveFile(const string &oldPath, const string &newPath, bool isSupportCrossPolicy)
664 {
665     bool errRet = false;
666     if (!IsFileExists(oldPath) || IsFileExists(newPath)) {
667         return errRet;
668     }
669 
670     errRet = (rename(oldPath.c_str(), newPath.c_str()) == E_SUCCESS);
671     if (!errRet && isSupportCrossPolicy && errno == CROSS_POLICY_ERR) {
672         errRet = CopyFileAndDelSrc(oldPath, newPath);
673     }
674     return errRet;
675 }
676 
CopyFileUtil(const string & filePath,const string & newPath)677 bool MediaFileUtils::CopyFileUtil(const string &filePath, const string &newPath)
678 {
679     struct stat fst{};
680     bool errCode = false;
681     if (filePath.size() >= PATH_MAX) {
682         MEDIA_ERR_LOG("File path too long %{public}d", static_cast<int>(filePath.size()));
683         return errCode;
684     }
685     MEDIA_DEBUG_LOG("File path is %{private}s", filePath.c_str());
686     string absFilePath;
687     if (!PathToRealPath(filePath, absFilePath)) {
688         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
689         return errCode;
690     }
691     if (absFilePath.empty()) {
692         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path:%{public}s %{public}d",
693                       filePath.c_str(), errno);
694         return errCode;
695     }
696 
697     int32_t source = open(absFilePath.c_str(), O_RDONLY);
698     if (source == -1) {
699         MEDIA_ERR_LOG("Open failed for source file, errno: %{public}d", errno);
700         return errCode;
701     }
702 
703     int32_t dest = open(newPath.c_str(), O_WRONLY | O_CREAT, CHOWN_RO_USR_GRP);
704     if (dest == -1) {
705         MEDIA_ERR_LOG("Open failed for destination file %{public}d", errno);
706         close(source);
707         return errCode;
708     }
709 
710     if (fstat(source, &fst) == E_SUCCESS) {
711         // Copy file content
712         if (sendfile(dest, source, nullptr, fst.st_size) != E_ERR) {
713             // Copy ownership and mode of source file
714             if (fchown(dest, fst.st_uid, fst.st_gid) == E_SUCCESS &&
715                 fchmod(dest, fst.st_mode) == E_SUCCESS) {
716                 errCode = true;
717             }
718         }
719     }
720 
721     close(source);
722     close(dest);
723 
724     return errCode;
725 }
726 
DecodeAsset(int32_t fd)727 static std::unique_ptr<Picture> DecodeAsset(int32_t fd)
728 {
729     if (fd < 0) {
730         MEDIA_ERR_LOG("fd = %{public}d is invalid", fd);
731         return nullptr;
732     }
733     MediaLibraryTracer tracer;
734     tracer.Start("DecodeAsset");
735 
736     SourceOptions opts;
737     uint32_t err = E_OK;
738     unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(fd, opts, err);
739     CHECK_AND_RETURN_RET_LOG(imageSource != nullptr, nullptr, "CreateImageSource failed, err: %{public}u", err);
740 
741     DecodingOptionsForPicture decodeOptions;
742     std::unique_ptr<Picture> picturePtr = imageSource->CreatePicture(decodeOptions, err);
743     CHECK_AND_RETURN_RET_LOG(picturePtr != nullptr, nullptr, "CreatePicture failed, err: %{public}u", err);
744     return picturePtr;
745 }
746 
EncodeSaveAsset(std::unique_ptr<Picture> picturePtr,const std::string & mimeType,int32_t dstFd)747 static bool EncodeSaveAsset(std::unique_ptr<Picture> picturePtr, const std::string &mimeType, int32_t dstFd)
748 {
749     if (picturePtr == nullptr) {
750         MEDIA_ERR_LOG("picturePtr is nullptr");
751         return false;
752     }
753     MediaLibraryTracer tracer;
754     tracer.Start("EncodeSaveAsset");
755 
756     Media::ImagePacker imagePacker;
757     Media::PackOption packOption;
758     packOption.format = mimeType;
759     packOption.desiredDynamicRange = EncodeDynamicRange::AUTO;
760     packOption.needsPackProperties = true;
761 
762     int32_t ret = imagePacker.StartPacking(dstFd, packOption);
763     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, false, "StartPacking failed, ret: %{public}d", ret);
764     ret = imagePacker.AddPicture(*(picturePtr));
765     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, false, "AddPicture failed, ret: %{public}d", ret);
766     ret = imagePacker.FinalizePacking();
767     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, false, "FinalizePacking failed, ret: %{public}d", ret);
768     return true;
769 }
770 
DecodeEncodeSaveAsset(int32_t srcFd,int32_t dstFd,const std::string & extension)771 static bool DecodeEncodeSaveAsset(int32_t srcFd, int32_t dstFd, const std::string &extension)
772 {
773     std::unique_ptr<Picture> picturePtr = DecodeAsset(srcFd);
774     if (picturePtr == nullptr) {
775         MEDIA_ERR_LOG("DecodeAsset failed");
776         return false;
777     }
778 
779     std::string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension, MEDIA_MIME_TYPE_MAP);
780     if (!EncodeSaveAsset(std::move(picturePtr), mimeType, dstFd)) {
781         MEDIA_ERR_LOG("EncodeAsset mimeType: %{public}s failed", mimeType.c_str());
782         return false;
783     }
784 
785     return true;
786 }
787 
ConvertFormatCopy(const std::string & srcFile,const std::string & dstFile,const std::string & extension)788 bool MediaFileUtils::ConvertFormatCopy(const std::string &srcFile, const std::string &dstFile,
789     const std::string &extension)
790 {
791     MEDIA_DEBUG_LOG("ConvertFormatCopy srcFile: %{public}s, dstFile: %{public}s, extension: %{public}s",
792         srcFile.c_str(), dstFile.c_str(), extension.c_str());
793     if (srcFile.size() >= PATH_MAX) {
794         MEDIA_ERR_LOG("File path too long %{public}d", static_cast<int>(srcFile.size()));
795         return false;
796     }
797     string absFilePath;
798     if (!PathToRealPath(srcFile, absFilePath)) {
799         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", srcFile.c_str());
800         return false;
801     }
802     if (absFilePath.empty()) {
803         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path:%{public}s %{public}d",
804                       srcFile.c_str(), errno);
805         return false;
806     }
807 
808     auto normalizedDstPath = std::filesystem::absolute(dstFile).lexically_normal();
809     if (normalizedDstPath.empty()) {
810         MEDIA_ERR_LOG("Failed to obtain the canonical path for destination path:%{public}s", srcFile.c_str());
811         return false;
812     }
813     UniqueFd srcFd(open(absFilePath.c_str(), O_RDONLY));
814     if (srcFd.Get() == E_ERR) {
815         MEDIA_ERR_LOG("Open failed for source file, errno: %{public}d", errno);
816         return false;
817     }
818     UniqueFd dstFd(open(normalizedDstPath.c_str(), O_WRONLY | O_CREAT, CHOWN_RO_USR_GRP));
819     if (dstFd.Get() == E_ERR) {
820         MEDIA_ERR_LOG("Open failed for destination file %{public}d", errno);
821         return false;
822     }
823 
824     if (!DecodeEncodeSaveAsset(srcFd.Get(), dstFd.Get(), extension)) {
825         MEDIA_ERR_LOG("DecodeEncodeSaveAsset failed");
826         return false;
827     }
828 
829     bool errCode = false;
830     struct stat fst{};
831     if (fstat(srcFd.Get(), &fst) == E_SUCCESS) {
832         // Copy ownership and mode of source file
833         if (fchown(dstFd.Get(), fst.st_uid, fst.st_gid) == E_SUCCESS && fchmod(dstFd.Get(), fst.st_mode) == E_SUCCESS) {
834             errCode = true;
835         }
836     }
837 
838     return errCode;
839 }
840 
ConvertFormatExtraDataDirectory(const std::string & srcDir,const std::string & dstDir,const std::string & extension)841 bool MediaFileUtils::ConvertFormatExtraDataDirectory(const std::string &srcDir, const std::string &dstDir,
842     const std::string &extension)
843 {
844     if (srcDir.empty() || dstDir.empty()) {
845         MEDIA_ERR_LOG("srcDir or dstDir is empty");
846         return E_MODIFY_DATA_FAIL;
847     }
848     if (!IsFileExists(srcDir)) {
849         MEDIA_ERR_LOG("SrcDir: %{public}s is not exist", srcDir.c_str());
850         return E_NO_SUCH_FILE;
851     }
852     if (IsFileExists(dstDir)) {
853         MEDIA_ERR_LOG("DstDir: %{public}s exists", dstDir.c_str());
854         return E_FILE_EXIST;
855     }
856     if (!IsDirectory(srcDir) || !CreateDirectory(dstDir)) {
857         MEDIA_ERR_LOG("srcDir is not directory or Create dstDir failed");
858         return E_FAIL;
859     }
860 
861     std::string sourceFilePath = srcDir + "/source." + GetExtensionFromPath(srcDir);
862     for (const auto& entry : std::filesystem::recursive_directory_iterator(srcDir)) {
863         std::string srcFilePath = entry.path();
864         std::string tmpFilePath = srcFilePath;
865         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
866         if (entry.is_directory()) {
867             if (!CreateDirectory(dstFilePath)) {
868                 MEDIA_ERR_LOG("Create dir:%{public}s failed", DesensitizePath(dstFilePath).c_str());
869                 return E_FAIL;
870             }
871         } else if (entry.is_regular_file()) {
872             error_code ec;
873             bool ret = false;
874             bool isEqual = std::filesystem::equivalent(srcFilePath, sourceFilePath, ec);
875             if (isEqual) {
876                 dstFilePath = dstDir + "/source." + extension;
877                 ret = ConvertFormatCopy(srcFilePath, dstFilePath, extension);
878             } else {
879                 ret = CopyFileUtil(srcFilePath, dstFilePath);
880             }
881             if (!ret) {
882                 MEDIA_ERR_LOG("copyFile failed, isSrcFile: %{public}d", isEqual);
883                 return E_FAIL;
884             }
885         } else {
886             MEDIA_ERR_LOG("Unhandled path type, path:%{public}s", DesensitizePath(srcFilePath).c_str());
887             return E_FAIL;
888         }
889     }
890     return E_OK;
891 }
892 
CopyFileSafe(const string & filePath,const string & newPath)893 bool MediaFileUtils::CopyFileSafe(const string &filePath, const string &newPath)
894 {
895     if (newPath.empty()) {
896         MEDIA_ERR_LOG("newPath is empty");
897         return false;
898     }
899     string newTempPath = newPath + "_" + std::to_string(MediaFileUtils::UTCTimeMilliSeconds());
900     if (!CopyFileUtil(filePath, newTempPath)) {
901         MEDIA_ERR_LOG("copy file errno: %{public}d", errno);
902         if (!DeleteFile(newTempPath)) {
903             MEDIA_ERR_LOG("del temp file errno: %{public}d", errno);
904         }
905         return false;
906     }
907     return rename(newTempPath.c_str(), newPath.c_str()) == E_OK;
908 }
909 
SetDeletionRecord(int fd,const string & fileName)910 void MediaFileUtils::SetDeletionRecord(int fd, const string &fileName)
911 {
912     unsigned int flags = 0;
913     int ret = -1;
914     ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags);
915     if (ret < 0) {
916         MEDIA_ERR_LOG("File %{public}s Failed to get flags, errno is %{public}d", fileName.c_str(), errno);
917         return;
918     }
919 
920     if (flags & HMFS_MONITOR_FL) {
921         return;
922     }
923     flags |= HMFS_MONITOR_FL;
924     ret = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags);
925     if (ret < 0) {
926         MEDIA_ERR_LOG("File %{public}s Failed to set flags, errno is %{public}d", fileName.c_str(), errno);
927         return;
928     }
929     MEDIA_INFO_LOG("Flie %{public}s Set Delete control flags is success", fileName.c_str());
930 }
931 
MediaFileDeletionRecord()932 void MediaFileUtils::MediaFileDeletionRecord()
933 {
934     int fd = -1;
935     int bucketFd = -1;
936     string path;
937     struct dirent* dirEntry;
938     DIR* fileDir;
939     MEDIA_INFO_LOG("Set DeletionRecord for directory");
940     for (auto &dir : SET_LISTEN_DIR) {
941         path = LISTENING_BASE_PATH + dir;
942         fd = open(path.c_str(), O_RDONLY);
943         if (fd < 0) {
944             MEDIA_ERR_LOG("Failed to open the Dir, errno is %{public}d, %{public}s", errno, dir.c_str());
945             continue;
946         }
947         SetDeletionRecord(fd, dir);
948         close(fd);
949         if ((strcmp(dir.c_str(), ".thumbs") == 0) || (strcmp(dir.c_str(), ".editData") == 0)) {
950             continue;
951         }
952         if ((fileDir = opendir(path.c_str())) == nullptr) {
953             MEDIA_ERR_LOG("dir not exist: %{private}s, error: %{public}d", path.c_str(), errno);
954             continue;
955         }
956         while ((dirEntry = readdir(fileDir)) != nullptr) {
957             if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0)) {
958                 continue;
959             }
960             std::string fileName = path + "/" + dirEntry->d_name;
961             bucketFd = open(fileName.c_str(), O_RDONLY);
962             if (bucketFd < 0) {
963                 MEDIA_ERR_LOG("Failed to open the bucketFd Dir error: %{public}d", errno);
964                 continue;
965             }
966             SetDeletionRecord(bucketFd, dirEntry->d_name);
967             close(bucketFd);
968         }
969         closedir(fileDir);
970     }
971 }
972 
WriteStrToFile(const string & filePath,const string & str)973 bool MediaFileUtils::WriteStrToFile(const string &filePath, const string &str)
974 {
975     if (filePath.empty()) {
976         MEDIA_ERR_LOG("FilePath is empty");
977         return false;
978     }
979     if (str.empty()) {
980         MEDIA_ERR_LOG("Write str is empty");
981         return false;
982     }
983 
984     if (!IsFileExists(filePath)) {
985         MEDIA_ERR_LOG("Can not get FilePath %{private}s", filePath.c_str());
986         return false;
987     }
988 
989     ofstream file(filePath);
990     if (!file.is_open()) {
991         MEDIA_ERR_LOG("Can not open FilePath %{private}s", filePath.c_str());
992         return false;
993     }
994 
995     file << str;
996     file.close();
997     if (!file.good()) {
998         MEDIA_ERR_LOG("Can not write FilePath %{private}s", filePath.c_str());
999         return false;
1000     }
1001     return true;
1002 }
1003 
ReadStrFromFile(const std::string & filePath,std::string & fileContent)1004 bool MediaFileUtils::ReadStrFromFile(const std::string &filePath, std::string &fileContent)
1005 {
1006     if (filePath.empty()) {
1007         MEDIA_ERR_LOG("FilePath is empty");
1008         return false;
1009     }
1010     if (!IsFileExists(filePath)) {
1011         MEDIA_ERR_LOG("Can not get FilePath %{private}s", filePath.c_str());
1012         return false;
1013     }
1014 
1015     string absFilePath;
1016     if (!PathToRealPath(filePath, absFilePath)) {
1017         MEDIA_ERR_LOG("Failed to open a nullptr path %{private}s, errno=%{public}d", filePath.c_str(), errno);
1018         return false;
1019     }
1020 
1021     ifstream file(absFilePath);
1022     if (!file.is_open()) {
1023         MEDIA_ERR_LOG("Can not open FilePath %{private}s", absFilePath.c_str());
1024         return false;
1025     }
1026     char ch;
1027     while (file.get(ch)) {
1028         fileContent += ch;
1029     }
1030     file.close();
1031     return true;
1032 }
1033 
CopyFile(int32_t rfd,int32_t wfd)1034 bool MediaFileUtils::CopyFile(int32_t rfd, int32_t wfd)
1035 {
1036     static const off_t sendSize1G = 1LL * 1024 * 1024 * 1024;
1037     static const off_t maxSendSize2G = 2LL * 1024 * 1024 * 1024;
1038     struct stat fst = {0};
1039     if (fstat(rfd, &fst) != 0) {
1040         MEDIA_INFO_LOG("fstat failed, errno=%{public}d", errno);
1041         return false;
1042     }
1043     off_t fileSize = fst.st_size;
1044 
1045     if (fileSize >= maxSendSize2G) {
1046         off_t offset = 0;
1047         while (offset < fileSize) {
1048             off_t sendSize = fileSize - offset;
1049             if (sendSize > sendSize1G) {
1050                 sendSize = sendSize1G;
1051             }
1052             if (sendfile(wfd, rfd, &offset, sendSize) != sendSize) {
1053                 MEDIA_INFO_LOG("send failed, errno=%{public}d", errno);
1054                 return false;
1055             }
1056         }
1057     } else {
1058         if (sendfile(wfd, rfd, nullptr, fst.st_size) != fileSize) {
1059             MEDIA_INFO_LOG("send failed, errno=%{public}d", errno);
1060             return false;
1061         }
1062     }
1063     return true;
1064 }
1065 
RenameDir(const string & oldPath,const string & newPath)1066 bool MediaFileUtils::RenameDir(const string &oldPath, const string &newPath)
1067 {
1068     bool errRet = false;
1069 
1070     if (IsDirectory(oldPath)) {
1071         errRet = (rename(oldPath.c_str(), newPath.c_str()) == E_SUCCESS);
1072         if (!errRet) {
1073             MEDIA_ERR_LOG("Failed RenameDir errno %{public}d", errno);
1074         }
1075     }
1076 
1077     return errRet;
1078 }
1079 
CheckStringSize(const string & str,const size_t max)1080 int32_t MediaFileUtils::CheckStringSize(const string &str, const size_t max)
1081 {
1082     size_t size = str.length();
1083     if (size == 0) {
1084         return -EINVAL;
1085     }
1086     if (size > max) {
1087         return -ENAMETOOLONG;
1088     }
1089     return E_OK;
1090 }
1091 
RegexCheck(const string & str,const string & regexStr)1092 static inline bool RegexCheck(const string &str, const string &regexStr)
1093 {
1094     const regex express(regexStr);
1095     return regex_search(str, express);
1096 }
1097 
CheckTitle(const string & title)1098 int32_t MediaFileUtils::CheckTitle(const string &title)
1099 {
1100     if (title.empty()) {
1101         MEDIA_ERR_LOG("Title is empty.");
1102         return -EINVAL;
1103     }
1104 
1105     static const string titleRegexCheck = R"([\\/:*?"<>|])";
1106     if (RegexCheck(title, titleRegexCheck)) {
1107         MEDIA_ERR_LOG("Failed to check title regex: %{private}s", title.c_str());
1108         return -EINVAL;
1109     }
1110     return E_OK;
1111 }
1112 
1113 int32_t MediaFileUtils::CheckTitleCompatible(const string& title)
1114 {
1115     CHECK_AND_RETURN_RET_LOG(!title.empty(), -EINVAL, "Title is empty.");
1116     static const string titleRegexCheck = R"([\.\\/:*?"'`<>|{}\[\]])";
1117     CHECK_AND_RETURN_RET_LOG(!RegexCheck(title, titleRegexCheck), -EINVAL,
1118         "Failed to check title regex: %{private}s", title.c_str());
1119     return E_OK;
1120 }
1121 
GetFileAssetUri(const std::string & fileAssetData,const std::string & displayName,const int32_t & fileId)1122 std::string MediaFileUtils::GetFileAssetUri(const std::string &fileAssetData, const std::string &displayName,
1123     const int32_t &fileId)
1124 {
1125     std::string filePath = fileAssetData;
1126     std::string baseUri = "file://media";
1127     size_t lastSlashInData = filePath.rfind('/');
1128     std::string fileNameInData =
1129         (lastSlashInData != std::string::npos) ? filePath.substr(lastSlashInData + 1) : filePath;
1130     size_t dotPos = fileNameInData.rfind('.');
1131     if (dotPos != std::string::npos) {
1132         fileNameInData = fileNameInData.substr(0, dotPos);
1133     }
1134     return baseUri + "/Photo/" + std::to_string(fileId) + "/" + fileNameInData + "/" + displayName;
1135 }
1136 
CheckDisplayName(const string & displayName,const bool compatibleCheckTitle)1137 int32_t MediaFileUtils::CheckDisplayName(const string &displayName, const bool compatibleCheckTitle)
1138 {
1139     int err = CheckStringSize(displayName, DISPLAYNAME_MAX);
1140     if (err < 0) {
1141         return err;
1142     }
1143     if (displayName.at(0) == '.') {
1144         return -EINVAL;
1145     }
1146     string title = GetTitleFromDisplayName(displayName);
1147     if (title.empty()) {
1148         return -EINVAL;
1149     }
1150 
1151     if (compatibleCheckTitle) {
1152         // 为了向前兼容,此处进行老版本的title校验
1153         return CheckTitleCompatible(title);
1154     }
1155     return CheckTitle(title);
1156 }
1157 
CheckFileDisplayName(const string & displayName)1158 int32_t MediaFileUtils::CheckFileDisplayName(const string &displayName)
1159 {
1160     int err = CheckStringSize(displayName, DISPLAYNAME_MAX);
1161     if (err < 0) {
1162         return err;
1163     }
1164     if (displayName.at(0) == '.') {
1165         return -EINVAL;
1166     }
1167     static const string TITLE_REGEX_CHECK = R"([\\/:*?"'`<>|{}\[\]])";
1168     if (RegexCheck(displayName, TITLE_REGEX_CHECK)) {
1169         MEDIA_ERR_LOG("Failed to check displayName regex: %{private}s", displayName.c_str());
1170         return -EINVAL;
1171     }
1172     return E_OK;
1173 }
1174 
1175 int32_t MediaFileUtils::CheckRelativePath(const std::string &relativePath)
1176 {
1177     if (relativePath.empty()) {
1178         return -EINVAL;
1179     }
1180 
1181     size_t firstPoint = (relativePath.front() == '/') ? 1 : 0;
1182     size_t lastPoint = 0;
1183     while (true) {
1184         lastPoint = relativePath.find_first_of('/', firstPoint);
1185         if (lastPoint == string::npos) {
1186             lastPoint = relativePath.length();
1187         }
1188         size_t len = lastPoint - firstPoint;
1189         if (len == 0) {
1190             MEDIA_ERR_LOG("relativePath %{private}s is invalid", relativePath.c_str());
1191             return -EINVAL;
1192         }
1193         string checkedDirName = relativePath.substr(firstPoint, len);
1194         if (CheckDentryName(checkedDirName) != E_OK) {
1195             MEDIA_ERR_LOG("Dir Name %{private}s is invalid in path %{private}s",
1196                 checkedDirName.c_str(), relativePath.c_str());
1197             return -EINVAL;
1198         }
1199         if (lastPoint == relativePath.length()) {
1200             break;
1201         }
1202         firstPoint = lastPoint + 1;
1203         if (firstPoint == relativePath.length()) {
1204             break;
1205         }
1206     }
1207     return E_OK;
1208 }
1209 
1210 bool MediaFileUtils::CheckDisplayLevel(const int32_t &displayLevel)
1211 {
1212     if (PORTRAIT_PAGE_MODE.find(displayLevel) == PORTRAIT_PAGE_MODE.end()) {
1213         MEDIA_ERR_LOG("display level %{private}d is invalid", displayLevel);
1214         return false;
1215     }
1216     return true;
1217 }
1218 
1219 string MediaFileUtils::GetHighlightPath(const string &uri)
1220 {
1221     int prefixLen = 0;
1222     string uriPrefix = "datashare:///media";
1223     if (uri.find(uriPrefix) != string::npos) {
1224         prefixLen = static_cast<int>(uriPrefix.length());
1225     } else if (uri.find(ML_FILE_URI_PREFIX) != string::npos) {
1226         prefixLen = static_cast<int>(ML_FILE_URI_PREFIX.length());
1227     } else {
1228         return "";
1229     }
1230 
1231     string path;
1232     if (IsFileExists(ROOT_MEDIA_DIR + HIGHLIGHT_INFO_OLD)) {
1233         path = "/storage/cloud/files/.thumbs" + uri.substr(prefixLen);
1234     } else {
1235         path = "/storage/cloud/files" + uri.substr(prefixLen);
1236     }
1237 
1238     return path;
1239 }
1240 
1241 string MediaFileUtils::GetHighlightVideoPath(const string &uri)
1242 {
1243     int prefixLen = 0;
1244     string uriPrefix = "datashare:///media";
1245     if (uri.find(uriPrefix) != string::npos) {
1246         prefixLen = static_cast<int>(uriPrefix.length());
1247     } else if (uri.find(ML_FILE_URI_PREFIX) != string::npos) {
1248         prefixLen = static_cast<int>(ML_FILE_URI_PREFIX.length());
1249     } else {
1250         return "";
1251     }
1252     string path = "/storage/cloud/files" + uri.substr(prefixLen);
1253     return path;
1254 }
1255 
1256 void MediaFileUtils::FormatRelativePath(string &relativePath)
1257 {
1258     if (relativePath.empty()) {
1259         return;
1260     }
1261     string FormatRelativePath = relativePath;
1262     if (relativePath.back() != '/') {
1263         relativePath += '/';
1264     }
1265     if (relativePath.front() == '/') {
1266         relativePath = relativePath.substr(1);
1267     }
1268 }
1269 
1270 void MediaFileUtils::GetRootDirFromRelativePath(const string &relativePath, string &rootDir)
1271 {
1272     rootDir = relativePath;
1273     if (relativePath.empty()) {
1274         return;
1275     }
1276     if (relativePath.back() != '/') {
1277         rootDir += '/';
1278     }
1279     if (rootDir[0] == '/') {
1280         size_t dirIndex = rootDir.find_first_of('/', 1);
1281         if (dirIndex == string::npos) {
1282             return;
1283         }
1284         rootDir = rootDir.substr(1, dirIndex);
1285     } else {
1286         size_t dirIndex = rootDir.find_first_of('/');
1287         if (dirIndex == string::npos) {
1288             return;
1289         }
1290         rootDir = rootDir.substr(0, dirIndex + 1);
1291     }
1292 }
1293 
1294 int32_t MediaFileUtils::CheckAlbumName(const string &albumName)
1295 {
1296     int err = CheckStringSize(albumName, DISPLAYNAME_MAX);
1297     if (err < 0) {
1298         MEDIA_ERR_LOG("Album name string size check failed: %{public}d, size is %{public}zu", err, albumName.length());
1299         return err;
1300     }
1301 
1302     static const string ALBUM_NAME_REGEX = R"([\.\\/:*?"'`<>|{}\[\]])";
1303     if (RegexCheck(albumName, ALBUM_NAME_REGEX)) {
1304         MEDIA_ERR_LOG("Failed to check album name regex: %{private}s", albumName.c_str());
1305         return -EINVAL;
1306     }
1307     return E_OK;
1308 }
1309 
1310 int32_t MediaFileUtils::CheckHighlightSubtitle(const string &highlightSubtitle)
1311 {
1312     size_t size = highlightSubtitle.length();
1313     CHECK_AND_RETURN_RET_LOG(size <= DISPLAYNAME_MAX, -ENAMETOOLONG,
1314         "Highlight subtitle string size check failed: size is %{public}zu", highlightSubtitle.length());
1315 
1316     static const string ALBUM_NAME_REGEX = R"([\.\\/:*?"'`<>|{}\[\]])";
1317     CHECK_AND_RETURN_RET_LOG(!RegexCheck(highlightSubtitle, ALBUM_NAME_REGEX), -EINVAL,
1318         "Failed to check album name regex: %{private}s", highlightSubtitle.c_str());
1319     return E_OK;
1320 }
1321 
CheckDentryName(const string & dentryName)1322 int32_t MediaFileUtils::CheckDentryName(const string &dentryName)
1323 {
1324     int err = CheckStringSize(dentryName, DISPLAYNAME_MAX);
1325     if (err < 0) {
1326         return err;
1327     }
1328 
1329     static const string DENTRY_REGEX_CHECK = R"([\\/:*?"'`<>|{}\[\]])";
1330     if (RegexCheck(dentryName, DENTRY_REGEX_CHECK)) {
1331         MEDIA_ERR_LOG("Failed to check dentry regex: %{private}s", dentryName.c_str());
1332         return -EINVAL;
1333     }
1334     return E_OK;
1335 }
1336 
1337 string MediaFileUtils::GetParentPath(const string &path)
1338 {
1339     string name;
1340     size_t slashIndex = path.rfind("/");
1341     if (slashIndex != string::npos) {
1342         name = path.substr(0, slashIndex);
1343     }
1344 
1345     return name;
1346 }
1347 
1348 string MediaFileUtils::GetTitleFromDisplayName(const string &displayName)
1349 {
1350     string title;
1351     if (!displayName.empty()) {
1352         string::size_type pos = displayName.find_last_of('.');
1353         if (pos == string::npos) {
1354             return "";
1355         }
1356         title = displayName.substr(0, pos);
1357     }
1358     return title;
1359 }
1360 
1361 int64_t MediaFileUtils::GetAlbumDateModified(const string &albumPath)
1362 {
1363     struct stat statInfo {};
1364     if (!albumPath.empty() && stat(albumPath.c_str(), &statInfo) == 0) {
1365         return (statInfo.st_mtime);
1366     }
1367     return 0;
1368 }
1369 
1370 int64_t MediaFileUtils::UTCTimeSeconds()
1371 {
1372     struct timespec t{};
1373     t.tv_sec = 0;
1374     t.tv_nsec = 0;
1375     clock_gettime(CLOCK_REALTIME, &t);
1376     return (int64_t)(t.tv_sec);
1377 }
1378 
1379 int64_t MediaFileUtils::UTCTimeMilliSeconds()
1380 {
1381     struct timespec t;
1382     constexpr int64_t SEC_TO_MSEC = 1e3;
1383     constexpr int64_t MSEC_TO_NSEC = 1e6;
1384     clock_gettime(CLOCK_REALTIME, &t);
1385     return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
1386 }
1387 
1388 int64_t MediaFileUtils::UTCTimeNanoSeconds()
1389 {
1390     struct timespec t {};
1391     constexpr int64_t SEC_TO_NSEC = 1e9;
1392     clock_gettime(CLOCK_REALTIME, &t);
1393     return t.tv_sec * SEC_TO_NSEC + t.tv_nsec;
1394 }
1395 
1396 string MediaFileUtils::StrCreateTime(const string &format, int64_t time)
1397 {
1398     char strTime[DEFAULT_TIME_SIZE] = "";
1399     CHECK_AND_RETURN_RET_LOG(time > 0, strTime, "invalid time: %{public}" PRId64, time);
1400     struct tm localTm;
1401     CHECK_AND_RETURN_RET_LOG(localtime_noenv_r(&time, &localTm) != nullptr, strTime,
1402         "localtime_noenv_r error: %{public}d", errno);
1403     CHECK_AND_PRINT_LOG(strftime(strTime, sizeof(strTime), format.c_str(), &localTm) != 0,
1404         "strftime error: %{public}d", errno);
1405     return strTime;
1406 }
1407 
1408 std::string MediaFileUtils::StrCreateTimeByMilliseconds(const string &format, int64_t time)
1409 {
1410     char strTime[DEFAULT_TIME_SIZE] = "";
1411     int64_t times = time / MSEC_TO_SEC;
1412     struct tm localTm;
1413 
1414     if (localtime_noenv_r(&times, &localTm) == nullptr) {
1415         MEDIA_ERR_LOG("localtime_noenv_r error: %{public}d", errno);
1416         CHECK_AND_PRINT_LOG(time >= 0, "Time value is negative: %{public}lld", static_cast<long long>(time));
1417         return strTime;
1418     }
1419 
1420     if (strftime(strTime, sizeof(strTime), format.c_str(), &localTm) == 0) {
1421         MEDIA_ERR_LOG("strftime error: %{public}d", errno);
1422     }
1423 
1424     if (time < 0) {
1425         MEDIA_ERR_LOG("Time value is negative: %{public}lld", static_cast<long long>(time));
1426     }
1427     return strTime;
1428 }
1429 
1430 string MediaFileUtils::GetIdFromUri(const string &uri)
1431 {
1432     return MediaFileUri(uri).GetFileId();
1433 }
1434 
1435 string MediaFileUtils::GetNetworkIdFromUri(const string &uri)
1436 {
1437     return MediaFileUri(uri).GetNetworkId();
1438 }
1439 
1440 string MediaFileUtils::UpdatePath(const string &path, const string &uri)
1441 {
1442     MediaLibraryTracer tracer;
1443     tracer.Start("MediaFileUtils::UpdatePath");
1444 
1445     string retStr = path;
1446     MEDIA_DEBUG_LOG("MediaFileUtils::UpdatePath path = %{private}s, uri = %{private}s", path.c_str(), uri.c_str());
1447     if (path.empty() || uri.empty()) {
1448         return retStr;
1449     }
1450 
1451     string networkId = GetNetworkIdFromUri(uri);
1452     if (networkId.empty()) {
1453         MEDIA_DEBUG_LOG("MediaFileUtils::UpdatePath retStr = %{private}s", retStr.c_str());
1454         return retStr;
1455     }
1456 
1457     size_t pos = path.find(MEDIA_DATA_DEVICE_PATH);
1458     if (pos == string::npos) {
1459         return retStr;
1460     }
1461 
1462     string beginStr = path.substr(0, pos);
1463     if (beginStr.empty()) {
1464         return retStr;
1465     }
1466 
1467     string endStr = path.substr(pos + MEDIA_DATA_DEVICE_PATH.length());
1468     CHECK_AND_RETURN_RET(!endStr.empty(), retStr);
1469 
1470     retStr = beginStr + networkId + endStr;
1471     MEDIA_DEBUG_LOG("MediaFileUtils::UpdatePath retStr = %{private}s", retStr.c_str());
1472     return retStr;
1473 }
1474 
1475 MediaType MediaFileUtils::GetMediaType(const string &filePath)
1476 {
1477     if (filePath.empty()) {
1478         return MEDIA_TYPE_ALL;
1479     }
1480 
1481     string extention = GetExtensionFromPath(filePath);
1482     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention, MEDIA_MIME_TYPE_MAP);
1483     return MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1484 }
1485 
1486 MediaType MediaFileUtils::GetMediaTypeNotSupported(const string &filePath)
1487 {
1488     if (filePath.empty()) {
1489         return MEDIA_TYPE_ALL;
1490     }
1491 
1492     string extention = GetExtensionFromPath(filePath);
1493     string mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extention, MEDIA_EXTRA_MIME_TYPE_MAP);
1494     return MimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
1495 }
1496 
1497 string MediaFileUtils::SplitByChar(const string &str, const char split)
1498 {
1499     size_t splitIndex = str.find_last_of(split);
1500     return (splitIndex == string::npos) ? ("") : (str.substr(splitIndex + 1));
1501 }
1502 
1503 string MediaFileUtils::GetExtensionFromPath(const string &path)
1504 {
1505     string extention = SplitByChar(path, '.');
1506     if (!extention.empty()) {
1507         transform(extention.begin(), extention.end(), extention.begin(), ::tolower);
1508     }
1509     return extention;
1510 }
1511 
1512 static void SendHmdfsCallerInfoToIoctl(const int32_t fd, const string &clientBundleName)
1513 {
1514     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
1515     HmdfsCallerInfo callerInfo;
1516     callerInfo.tokenId = tokenId;
1517 
1518     if (strcpy_s(callerInfo.bundleName, sizeof(callerInfo.bundleName), clientBundleName.c_str()) != 0) {
1519         MEDIA_ERR_LOG("Failed to copy clientBundleName: %{public}s", clientBundleName.c_str());
1520     } else {
1521         MEDIA_DEBUG_LOG("clientBundleName = %{public}s", clientBundleName.c_str());
1522         int32_t ret = ioctl(fd, HMDFS_IOC_GET_CALLER_INFO, callerInfo);
1523         if (ret < 0) {
1524             MEDIA_DEBUG_LOG("Failed to set callerInfo to fd: %{public}d, error: %{public}d", fd, errno);
1525         }
1526     }
1527 }
1528 
1529 int32_t MediaFileUtils::OpenFile(const string &filePath, const string &mode, const string &clientbundleName)
1530 {
1531     int32_t errCode = E_ERR;
1532 
1533     if (filePath.empty() || mode.empty()) {
1534         MEDIA_ERR_LOG("Invalid open argument! mode: %{private}s, path: %{private}s", mode.c_str(), filePath.c_str());
1535         return errCode;
1536     }
1537 
1538     static const unordered_map<string, int32_t> MEDIA_OPEN_MODE_MAP = {
1539         { MEDIA_FILEMODE_READONLY, O_RDONLY },
1540         { MEDIA_FILEMODE_WRITEONLY, O_WRONLY },
1541         { MEDIA_FILEMODE_READWRITE, O_RDWR },
1542         { MEDIA_FILEMODE_WRITETRUNCATE, O_WRONLY | O_TRUNC },
1543         { MEDIA_FILEMODE_WRITEAPPEND, O_WRONLY | O_APPEND },
1544         { MEDIA_FILEMODE_READWRITETRUNCATE, O_RDWR | O_TRUNC },
1545         { MEDIA_FILEMODE_READWRITEAPPEND, O_RDWR | O_APPEND },
1546     };
1547     if (MEDIA_OPEN_MODE_MAP.find(mode) == MEDIA_OPEN_MODE_MAP.end()) {
1548         return E_ERR;
1549     }
1550 
1551     if (filePath.size() >= PATH_MAX) {
1552         MEDIA_ERR_LOG("File path too long %{public}d", (int)filePath.size());
1553         return errCode;
1554     }
1555     string absFilePath;
1556     if (!PathToRealPath(filePath, absFilePath)) {
1557         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
1558         return errCode;
1559     }
1560     if (absFilePath.empty()) {
1561         MEDIA_ERR_LOG("Failed to obtain the canonical path for source path %{public}d %{private}s",
1562                       errno, filePath.c_str());
1563         return errCode;
1564     }
1565     MEDIA_DEBUG_LOG("File absFilePath is %{private}s", absFilePath.c_str());
1566     int32_t fd = open(absFilePath.c_str(), MEDIA_OPEN_MODE_MAP.at(mode));
1567     if (clientbundleName.empty()) {
1568         MEDIA_DEBUG_LOG("ClientbundleName is empty,failed to to set caller_info to fd");
1569     } else {
1570         SendHmdfsCallerInfoToIoctl(fd, clientbundleName);
1571     }
1572     return fd;
1573 }
1574 
1575 int32_t MediaFileUtils::CreateAsset(const string &filePath)
1576 {
1577     MediaLibraryTracer tracer;
1578     tracer.Start("MediaFileUtils::CreateAsset");
1579 
1580     int32_t errCode = E_ERR;
1581 
1582     if (filePath.empty()) {
1583         MEDIA_ERR_LOG("Filepath is empty");
1584         return E_VIOLATION_PARAMETERS;
1585     }
1586 
1587     if (IsFileExists(filePath)) {
1588         MEDIA_ERR_LOG("the file exists path: %{public}s", filePath.c_str());
1589         return E_FILE_EXIST;
1590     }
1591 
1592     size_t slashIndex = filePath.rfind('/');
1593     if (slashIndex != string::npos) {
1594         string fileName = filePath.substr(slashIndex + 1);
1595         if (!fileName.empty() && fileName.at(0) != '.') {
1596             size_t dotIndex = filePath.rfind('.');
1597             if ((dotIndex == string::npos) && (GetMediaType(filePath) != MEDIA_TYPE_FILE)) {
1598                 return errCode;
1599             }
1600         }
1601     }
1602 
1603     ofstream file(filePath);
1604     if (!file) {
1605         MEDIA_ERR_LOG("Output file path could not be created errno %{public}d", errno);
1606         return errCode;
1607     }
1608 
1609     file.close();
1610 
1611     return E_SUCCESS;
1612 }
1613 
1614 int32_t MediaFileUtils::ModifyAsset(const string &oldPath, const string &newPath)
1615 {
1616     int32_t err = E_MODIFY_DATA_FAIL;
1617 
1618     if (oldPath.empty() || newPath.empty()) {
1619         MEDIA_ERR_LOG("Failed to modify asset, oldPath: %{private}s or newPath: %{private}s is empty!",
1620             oldPath.c_str(), newPath.c_str());
1621         return err;
1622     }
1623     if (!IsFileExists(oldPath)) {
1624         MEDIA_ERR_LOG("Failed to modify asset, oldPath: %{private}s does not exist!", oldPath.c_str());
1625         return E_NO_SUCH_FILE;
1626     }
1627     if (IsFileExists(newPath)) {
1628         MEDIA_ERR_LOG("Failed to modify asset, newPath: %{private}s is already exist!", newPath.c_str());
1629         return E_FILE_EXIST;
1630     }
1631     err = rename(oldPath.c_str(), newPath.c_str());
1632     if (err < 0) {
1633         int errorno = errno;
1634         MEDIA_ERR_LOG("Failed rename, errno: %{public}d, old path: %{public}s exists: %{public}d, "
1635             "new path: %{public}s exists: %{public}d", errorno, DesensitizePath(oldPath).c_str(),
1636             IsFileExists(oldPath), DesensitizePath(newPath).c_str(), IsFileExists(newPath));
1637         if (errorno == EACCES) {
1638             PrintStatInformation(GetParentPath(oldPath));
1639         }
1640         return E_FILE_OPER_FAIL;
1641     }
1642 
1643     return E_SUCCESS;
1644 }
1645 
1646 int32_t MediaFileUtils::OpenAsset(const string &filePath, const string &mode)
1647 {
1648     if (filePath.empty()) {
1649         return E_INVALID_PATH;
1650     }
1651     if (mode.empty()) {
1652         return E_INVALID_MODE;
1653     }
1654 
1655     int32_t flags = O_RDWR;
1656     if (mode == MEDIA_FILEMODE_READONLY) {
1657         flags = O_RDONLY;
1658     } else if (mode == MEDIA_FILEMODE_WRITEONLY) {
1659         flags = O_WRONLY;
1660     } else if (mode == MEDIA_FILEMODE_WRITETRUNCATE) {
1661         flags = O_WRONLY | O_TRUNC;
1662     } else if (mode == MEDIA_FILEMODE_WRITEAPPEND) {
1663         flags = O_WRONLY | O_APPEND;
1664     } else if (mode == MEDIA_FILEMODE_READWRITETRUNCATE) {
1665         flags = O_RDWR | O_TRUNC;
1666     }
1667 
1668     if (filePath.size() >= PATH_MAX) {
1669         MEDIA_ERR_LOG("File path too long %{public}d", (int)filePath.size());
1670         return E_INVALID_PATH;
1671     }
1672     MEDIA_DEBUG_LOG("File path is %{private}s", filePath.c_str());
1673     std::string absFilePath;
1674     if (!PathToRealPath(filePath, absFilePath)) {
1675         MEDIA_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
1676         return E_INVALID_PATH;
1677     }
1678     CHECK_AND_RETURN_RET_LOG(!absFilePath.empty(), E_INVALID_PATH,
1679         "Failed to obtain the canonical path for source path %{private}s %{public}d", filePath.c_str(), errno);
1680 
1681     MEDIA_DEBUG_LOG("File absFilePath is %{private}s", absFilePath.c_str());
1682     return open(absFilePath.c_str(), flags);
1683 }
1684 
1685 int32_t MediaFileUtils::CloseAsset(int32_t fd)
1686 {
1687     return close(fd);
1688 }
1689 
1690 std::string MediaFileUtils::GetMediaTypeUri(MediaType mediaType)
1691 {
1692     switch (mediaType) {
1693         case MEDIA_TYPE_AUDIO:
1694             return MEDIALIBRARY_AUDIO_URI;
1695         case MEDIA_TYPE_VIDEO:
1696             return MEDIALIBRARY_VIDEO_URI;
1697         case MEDIA_TYPE_IMAGE:
1698             return MEDIALIBRARY_IMAGE_URI;
1699         case MEDIA_TYPE_SMARTALBUM:
1700             return MEDIALIBRARY_SMARTALBUM_CHANGE_URI;
1701         case MEDIA_TYPE_DEVICE:
1702             return MEDIALIBRARY_DEVICE_URI;
1703         case MEDIA_TYPE_FILE:
1704         default:
1705             return MEDIALIBRARY_FILE_URI;
1706     }
1707 }
1708 
1709 std::string MediaFileUtils::GetMediaTypeUriV10(MediaType mediaType)
1710 {
1711     switch (mediaType) {
1712         case MEDIA_TYPE_AUDIO:
1713             return AudioColumn::DEFAULT_AUDIO_URI;
1714         case MEDIA_TYPE_VIDEO:
1715         case MEDIA_TYPE_IMAGE:
1716             return PhotoColumn::DEFAULT_PHOTO_URI;
1717         case MEDIA_TYPE_SMARTALBUM:
1718             return MEDIALIBRARY_SMARTALBUM_CHANGE_URI;
1719         case MEDIA_TYPE_DEVICE:
1720             return MEDIALIBRARY_DEVICE_URI;
1721         case MEDIA_TYPE_FILE:
1722         default:
1723             return MEDIALIBRARY_FILE_URI;
1724     }
1725 }
1726 
1727 bool MediaFileUtils::CheckMode(const string &mode)
1728 {
1729     if (mode.empty()) {
1730         return false;
1731     }
1732     if (MEDIA_OPEN_MODES.find(mode) != MEDIA_OPEN_MODES.end()) {
1733         return true;
1734     } else {
1735         MEDIA_ERR_LOG("Input Mode %{private}s is invalid", mode.c_str());
1736         return false;
1737     }
1738 }
1739 
1740 size_t MediaFileUtils::FindIgnoreCase(const std::string &str, const std::string &key)
1741 {
1742     auto it = search(str.begin(), str.end(), key.begin(), key.end(), [](const char a, const char b) {
1743         return ::tolower(a) == ::tolower(b);
1744     });
1745     if (it == str.end()) {
1746         return string::npos;
1747     }
1748     size_t pos = static_cast<size_t>(it - str.begin());
1749     return (pos > 0) ? pos : 0;
1750 }
1751 
1752 int64_t MediaFileUtils::GetVirtualIdByType(int32_t id, MediaType type)
1753 {
1754     switch (type) {
1755         case MediaType::MEDIA_TYPE_IMAGE:
1756         case MediaType::MEDIA_TYPE_VIDEO: {
1757             return (int64_t) id * VIRTUAL_ID_DIVIDER - PHOTO_VIRTUAL_IDENTIFIER;
1758         }
1759         case MediaType::MEDIA_TYPE_AUDIO: {
1760             return (int64_t) id * VIRTUAL_ID_DIVIDER - AUDIO_VIRTUAL_IDENTIFIER;
1761         }
1762         default: {
1763             return (int64_t)id * VIRTUAL_ID_DIVIDER - FILE_VIRTUAL_IDENTIFIER;
1764         }
1765     }
1766 }
1767 
1768 double MediaFileUtils::GetRealIdByTable(int32_t virtualId, const string &tableName)
1769 {
1770     if (tableName == PhotoColumn::PHOTOS_TABLE) {
1771         return (double) (virtualId + PHOTO_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1772     } else if (tableName == AudioColumn::AUDIOS_TABLE) {
1773         return (double) (virtualId + AUDIO_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1774     } else {
1775         return (double) (virtualId + FILE_VIRTUAL_IDENTIFIER) / VIRTUAL_ID_DIVIDER;
1776     }
1777 }
1778 
1779 string MediaFileUtils::GetVirtualUriFromRealUri(const string &uri, const string &extrUri)
1780 {
1781     if ((uri.find(PhotoColumn::PHOTO_TYPE_URI) != string::npos) ||
1782         (uri.find(AudioColumn::AUDIO_TYPE_URI) != string::npos) ||
1783         (uri.find(PhotoColumn::HIGHTLIGHT_COVER_URI) != string::npos) ||
1784         (uri.find(URI_MTP_OPERATION) != string::npos)) {
1785         return uri;
1786     }
1787 
1788     string pureUri = uri;
1789     string suffixUri;
1790     size_t questionMaskPoint = uri.rfind('?');
1791     size_t hashKeyPoint = uri.rfind('#');
1792     if (questionMaskPoint != string::npos) {
1793         suffixUri = uri.substr(questionMaskPoint);
1794         pureUri = uri.substr(0, questionMaskPoint);
1795     } else if (hashKeyPoint != string::npos) {
1796         suffixUri = uri.substr(hashKeyPoint);
1797         pureUri = uri.substr(0, hashKeyPoint);
1798     }
1799 
1800     MediaFileUri fileUri(pureUri);
1801     string fileId = fileUri.GetFileId();
1802     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
1803         return uri;
1804     }
1805     int32_t id;
1806     if (!StrToInt(fileId, id)) {
1807         MEDIA_ERR_LOG("invalid fileuri %{private}s", uri.c_str());
1808         return uri;
1809     }
1810     int64_t virtualId;
1811     MediaType type;
1812     if ((pureUri.find(MEDIALIBRARY_TYPE_IMAGE_URI) != string::npos)) {
1813         type = MediaType::MEDIA_TYPE_IMAGE;
1814         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_IMAGE);
1815     } else if (pureUri.find(MEDIALIBRARY_TYPE_VIDEO_URI) != string::npos) {
1816         type = MediaType::MEDIA_TYPE_VIDEO;
1817         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_VIDEO);
1818     } else if ((pureUri.find(MEDIALIBRARY_TYPE_AUDIO_URI) != string::npos)) {
1819         type = MediaType::MEDIA_TYPE_AUDIO;
1820         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_AUDIO);
1821     } else {
1822         type = MediaType::MEDIA_TYPE_FILE;
1823         virtualId = GetVirtualIdByType(id, MediaType::MEDIA_TYPE_FILE);
1824     }
1825     MediaFileUri virtualUri(type, to_string(virtualId), fileUri.GetNetworkId(),
1826         (fileUri.IsApi10() ? MEDIA_API_VERSION_V10 : MEDIA_API_VERSION_V9),
1827         (fileUri.IsApi10() ? extrUri : ""));
1828 
1829     return suffixUri.empty() ? virtualUri.ToString() : virtualUri.ToString() + suffixUri;
1830 }
1831 
1832 void GetExtrParamFromUri(const std::string &uri, std::string &displayName)
1833 {
1834     if (uri.find(PATH_PARA) != string::npos) {
1835         size_t lastSlashPosition = uri.rfind('/');
1836         if (lastSlashPosition != string::npos) {
1837             displayName = uri.substr(lastSlashPosition + 1);
1838         }
1839     }
1840 }
1841 
1842 void InitPureAndSuffixUri(string &pureUri, string &suffixUri, const string &uri)
1843 {
1844     size_t questionMaskPoint = uri.rfind('?');
1845     size_t hashKeyPoint = uri.rfind('#');
1846     if (questionMaskPoint != string::npos) {
1847         suffixUri = uri.substr(questionMaskPoint);
1848         pureUri = uri.substr(0, questionMaskPoint);
1849     } else if (hashKeyPoint != string::npos) {
1850         suffixUri = uri.substr(hashKeyPoint);
1851         pureUri = uri.substr(0, hashKeyPoint);
1852     }
1853 }
1854 
1855 string MediaFileUtils::GetRealUriFromVirtualUri(const string &uri)
1856 {
1857     if ((uri.find(PhotoColumn::PHOTO_TYPE_URI) != string::npos) ||
1858         (uri.find(AudioColumn::AUDIO_TYPE_URI) != string::npos) ||
1859         (uri.find(PhotoColumn::HIGHTLIGHT_COVER_URI) != string::npos) ||
1860         (uri.find(URI_MTP_OPERATION) != string::npos)) {
1861         return uri;
1862     }
1863 
1864     string pureUri = uri;
1865     string suffixUri;
1866     InitPureAndSuffixUri(pureUri, suffixUri, uri);
1867     MediaFileUri fileUri(pureUri);
1868     string fileId = fileUri.GetFileId();
1869     if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
1870         return uri;
1871     }
1872     int32_t id;
1873     if (!StrToInt(fileId, id)) {
1874         MEDIA_ERR_LOG("invalid fileuri %{private}s", uri.c_str());
1875         return uri;
1876     }
1877     int32_t realId = 0;
1878     MediaType type;
1879     if ((pureUri.find(MEDIALIBRARY_TYPE_IMAGE_URI) != string::npos)) {
1880         type = MediaType::MEDIA_TYPE_IMAGE;
1881         realId = static_cast<int32_t>(GetRealIdByTable(id, PhotoColumn::PHOTOS_TABLE));
1882     } else if (pureUri.find(MEDIALIBRARY_TYPE_VIDEO_URI) != string::npos) {
1883         type = MediaType::MEDIA_TYPE_VIDEO;
1884         realId = static_cast<int32_t>(GetRealIdByTable(id, PhotoColumn::PHOTOS_TABLE));
1885     } else if ((pureUri.find(MEDIALIBRARY_TYPE_AUDIO_URI) != string::npos)) {
1886         type = MediaType::MEDIA_TYPE_AUDIO;
1887         realId = static_cast<int32_t>(GetRealIdByTable(id, AudioColumn::AUDIOS_TABLE));
1888     } else {
1889         type = MediaType::MEDIA_TYPE_FILE;
1890         realId = static_cast<int32_t>(GetRealIdByTable(id, MEDIALIBRARY_TABLE));
1891     }
1892     string extrUri;
1893     if (fileUri.IsApi10()) {
1894         string displayName;
1895         GetExtrParamFromUri(pureUri, displayName);
1896         extrUri = GetExtraUri(displayName, fileUri.GetFilePath(), false);
1897     }
1898 
1899     MediaFileUri realUri(type, to_string(realId), fileUri.GetNetworkId(),
1900         (fileUri.IsApi10() ? MEDIA_API_VERSION_V10 : MEDIA_API_VERSION_V9), (fileUri.IsApi10() ? extrUri : ""));
1901 
1902     if (suffixUri.empty()) {
1903         return realUri.ToString();
1904     }
1905     return realUri.ToString() + suffixUri;
1906 }
1907 
1908 #ifdef MEDIALIBRARY_COMPATIBILITY
1909 string MediaFileUtils::GetTableFromVirtualUri(const std::string &virtualUri)
1910 {
1911     MediaFileUri uri(virtualUri);
1912     if (!uri.IsValid()) {
1913         MEDIA_ERR_LOG("virtual uri:%{private}s is invalid", virtualUri.c_str());
1914         return "";
1915     }
1916     string virtualId = uri.GetFileId();
1917     if (std::all_of(virtualId.begin(), virtualId.end(), ::isdigit)) {
1918         int64_t id = stol(virtualId);
1919         int64_t remainNumber = id % VIRTUAL_ID_DIVIDER;
1920         switch (remainNumber) {
1921             case VIRTUAL_ID_DIVIDER - PHOTO_VIRTUAL_IDENTIFIER:
1922                 return PhotoColumn::PHOTOS_TABLE;
1923             case VIRTUAL_ID_DIVIDER - AUDIO_VIRTUAL_IDENTIFIER:
1924                 return AudioColumn::AUDIOS_TABLE;
1925             case VIRTUAL_ID_DIVIDER - FILE_VIRTUAL_IDENTIFIER:
1926                 return MEDIALIBRARY_TABLE;
1927             default:
1928                 MEDIA_ERR_LOG("virtualId:%{public}ld is wrong", (long) id);
1929                 return "";
1930         }
1931     } else {
1932         MEDIA_ERR_LOG("virtual uri:%{private}s is invalid, can not get id", virtualUri.c_str());
1933         return "";
1934     }
1935 }
1936 #endif
1937 
1938 bool MediaFileUtils::IsUriV10(const string &mediaType)
1939 {
1940     return mediaType == URI_TYPE_PHOTO ||
1941         mediaType == URI_TYPE_PHOTO_ALBUM ||
1942         mediaType == URI_TYPE_AUDIO_V10;
1943 }
1944 
1945 bool MediaFileUtils::IsFileTablePath(const string &path)
1946 {
1947     if (path.empty() || path.size() <= ROOT_MEDIA_DIR.size()) {
1948         return false;
1949     }
1950 
1951     if (path.find(ROOT_MEDIA_DIR) == string::npos) {
1952         return false;
1953     }
1954 
1955     string relativePath = path.substr(ROOT_MEDIA_DIR.size());
1956     if ((relativePath.find(DOCS_PATH) == 0)) {
1957         return true;
1958     }
1959     return false;
1960 }
1961 
1962 bool MediaFileUtils::IsPhotoTablePath(const string &path)
1963 {
1964     if (path.empty() || path.size() <= ROOT_MEDIA_DIR.size()) {
1965         return false;
1966     }
1967 
1968     if (path.find(ROOT_MEDIA_DIR) == string::npos) {
1969         return false;
1970     }
1971 
1972     string relativePath = path.substr(ROOT_MEDIA_DIR.size());
1973 
1974     const vector<string> photoPathVector = {
1975         PHOTO_BUCKET, PIC_DIR_VALUES, VIDEO_DIR_VALUES, CAMERA_DIR_VALUES
1976     };
1977     for (auto &photoPath : photoPathVector) {
1978         if (relativePath.find(photoPath) == 0) {
1979             return true;
1980         }
1981     }
1982     return false;
1983 }
1984 
1985 bool MediaFileUtils::StartsWith(const std::string &str, const std::string &prefix)
1986 {
1987     return str.compare(0, prefix.size(), prefix) == 0;
1988 }
1989 
1990 bool MediaFileUtils::EndsWith(const std::string &str, const std::string &suffix)
1991 {
1992     if (str.length() < suffix.length()) {
1993         return false;
1994     }
1995     return str.rfind(suffix) == str.length() - suffix.length();
1996 }
1997 
1998 void MediaFileUtils::ReplaceAll(std::string &str, const std::string &from, const std::string &to)
1999 {
2000     size_t startPos = 0;
2001     while ((startPos = str.find(from, startPos)) != std::string::npos) {
2002         str.replace(startPos, from.length(), to);
2003         startPos += to.length();
2004     }
2005 }
2006 
2007 void MediaFileUtils::UriAppendKeyValue(string &uri, const string &key, std::string value)
2008 {
2009     string uriKey = key + '=';
2010     if (uri.find(uriKey) != string::npos) {
2011         return;
2012     }
2013 
2014     char queryMark = (uri.find('?') == string::npos) ? '?' : '&';
2015     string append = queryMark + key + '=' + value;
2016 
2017     size_t pos = uri.find('#');
2018     if (pos == string::npos) {
2019         uri += append;
2020     } else {
2021         uri.insert(pos, append);
2022     }
2023 }
2024 
2025 string MediaFileUtils::GetExtraUri(const string &displayName, const string &path, const bool isNeedEncode)
2026 {
2027     string extraUri = "/" + GetTitleFromDisplayName(GetFileName(path)) + "/" + displayName;
2028     if (!isNeedEncode) {
2029         return extraUri;
2030     }
2031     return MediaFileUtils::Encode(extraUri);
2032 }
2033 
2034 string MediaFileUtils::GetUriByExtrConditions(const string &prefix, const string &fileId, const string &suffix)
2035 {
2036     return prefix + fileId + suffix;
2037 }
2038 
2039 std::string MediaFileUtils::GetUriWithoutDisplayname(const string &uri)
2040 {
2041     if (uri.empty()) {
2042         return uri;
2043     }
2044 
2045     auto index = uri.rfind("/");
2046     if (index == string::npos) {
2047         return uri;
2048     }
2049 
2050     return uri.substr(0, index + 1);
2051 }
2052 
2053 string MediaFileUtils::Encode(const string &uri)
2054 {
2055     const unordered_set<char> uriCompentsSet = {
2056         ';', ',', '/', '?', ':', '@', '&',
2057         '=', '+', '$', '-', '_', '.', '!',
2058         '~', '*', '(', ')'
2059     };
2060     const int32_t encodeLen = 2;
2061     ostringstream outPutStream;
2062     outPutStream.fill('0');
2063     outPutStream << std::hex;
2064 
2065     for (unsigned char tmpChar : uri) {
2066         if (std::isalnum(tmpChar) || uriCompentsSet.find(tmpChar) != uriCompentsSet.end()) {
2067             outPutStream << tmpChar;
2068         } else {
2069             outPutStream << std::uppercase;
2070             outPutStream << '%' << std::setw(encodeLen) << static_cast<unsigned int>(tmpChar);
2071             outPutStream << std::nouppercase;
2072         }
2073     }
2074 
2075     return outPutStream.str();
2076 }
2077 
2078 string MediaFileUtils::AddDocsToRelativePath(const string &relativePath)
2079 {
2080     if (MediaFileUtils::StartsWith(relativePath, DOC_DIR_VALUES) ||
2081         MediaFileUtils::StartsWith(relativePath, DOWNLOAD_DIR_VALUES)) {
2082         return DOCS_PATH + relativePath;
2083     }
2084     return relativePath;
2085 }
2086 
2087 string MediaFileUtils::RemoveDocsFromRelativePath(const string &relativePath)
2088 {
2089     if (MediaFileUtils::StartsWith(relativePath, DOCS_PATH)) {
2090         return relativePath.substr(DOCS_PATH.size());
2091     }
2092     return relativePath;
2093 }
2094 
2095 int64_t MediaFileUtils::Timespec2Millisecond(const struct timespec &time)
2096 {
2097     return time.tv_sec * MSEC_TO_SEC + time.tv_nsec / MSEC_TO_NSEC;
2098 }
2099 
2100 string MediaFileUtils::GetTempMovingPhotoVideoPath(const string &imagePath)
2101 {
2102     size_t splitIndex = imagePath.find_last_of('.');
2103     size_t lastSlashIndex = imagePath.find_last_of('/');
2104     if (splitIndex == string::npos || (lastSlashIndex != string::npos && lastSlashIndex > splitIndex)) {
2105         return "";
2106     }
2107     return imagePath.substr(0, lastSlashIndex + 1) + "_temp" +
2108         imagePath.substr(lastSlashIndex + 1, splitIndex - lastSlashIndex - 1) + ".mp4";
2109 }
2110 
2111 string MediaFileUtils::GetMovingPhotoVideoPath(const string &imagePath)
2112 {
2113     size_t splitIndex = imagePath.find_last_of('.');
2114     size_t lastSlashIndex = imagePath.find_last_of('/');
2115     if (splitIndex == string::npos || (lastSlashIndex != string::npos && lastSlashIndex > splitIndex)) {
2116         return "";
2117     }
2118     return imagePath.substr(0, splitIndex) + ".mp4";
2119 }
2120 
2121 bool MediaFileUtils::CheckMovingPhotoExtension(const string &extension)
2122 {
2123     return IsMovingPhotoMimeType(MimeTypeUtils::GetMimeTypeFromExtension(extension, MEDIA_MIME_TYPE_MAP));
2124 }
2125 
2126 bool MediaFileUtils::IsMovingPhotoMimeType(const string &mimeType)
2127 {
2128     // image of moving photo must be image/jpeg, image/heif or image/heic
2129     return mimeType == "image/jpeg" || mimeType == "image/heif" || mimeType == "image/heic";
2130 }
2131 
2132 bool MediaFileUtils::CheckMovingPhotoVideoExtension(const string &extension)
2133 {
2134     // video of moving photo must be video/mp4
2135     return MimeTypeUtils::GetMimeTypeFromExtension(extension, MEDIA_MIME_TYPE_MAP) == "video/mp4";
2136 }
2137 
2138 bool MediaFileUtils::CheckMovingPhotoImage(const string &path)
2139 {
2140     return CheckMovingPhotoExtension(GetExtensionFromPath(path));
2141 }
2142 
2143 bool MediaFileUtils::CheckMovingPhotoVideo(const string &path)
2144 {
2145     string absFilePath;
2146     if (!PathToRealPath(path, absFilePath)) {
2147         MEDIA_ERR_LOG("Failed to get real path, path: %{private}s", path.c_str());
2148         return false;
2149     }
2150     if (absFilePath.empty()) {
2151         MEDIA_ERR_LOG("Failed to check path for %{private}s, errno: %{public}d", path.c_str(), errno);
2152         return false;
2153     }
2154 
2155     string extension = GetExtensionFromPath(absFilePath);
2156     if (!CheckMovingPhotoVideoExtension(extension)) {
2157         MEDIA_ERR_LOG("Failed to check extension (%{public}s) of moving photo video", extension.c_str());
2158         return false;
2159     }
2160 
2161     UniqueFd uniqueFd(open(absFilePath.c_str(), O_RDONLY));
2162     return CheckMovingPhotoVideo(uniqueFd);
2163 }
2164 
2165 bool MediaFileUtils::CheckMovingPhotoVideo(const UniqueFd &uniqueFd)
2166 {
2167     MediaLibraryTracer tracer;
2168     tracer.Start("MediaFileUtils::CheckMovingPhotoVideo");
2169 
2170     if (uniqueFd.Get() <= 0) {
2171         MEDIA_ERR_LOG("Failed to open video of moving photo, errno = %{public}d", errno);
2172         return false;
2173     }
2174     struct stat64 st;
2175     if (fstat64(uniqueFd.Get(), &st) != 0) {
2176         MEDIA_ERR_LOG("Failed to get file state, errno = %{public}d", errno);
2177         return false;
2178     }
2179 
2180     shared_ptr<AVMetadataHelper> avMetadataHelper = AVMetadataHelperFactory::CreateAVMetadataHelper();
2181     if (avMetadataHelper == nullptr) {
2182         MEDIA_WARN_LOG("Failed to create AVMetadataHelper, ignore checking duration");
2183         return true;
2184     }
2185 
2186     int32_t err = avMetadataHelper->SetSource(uniqueFd.Get(), 0,
2187         static_cast<int64_t>(st.st_size), AV_META_USAGE_META_ONLY);
2188     if (err != 0) {
2189         MEDIA_ERR_LOG("SetSource failed for the given file descriptor, err = %{public}d", err);
2190         return false;
2191     }
2192 
2193     unordered_map<int32_t, string> resultMap = avMetadataHelper->ResolveMetadata();
2194     if (resultMap.find(AV_KEY_DURATION) == resultMap.end()) {
2195         MEDIA_ERR_LOG("AV_KEY_DURATION does not exist");
2196         return false;
2197     }
2198     string durationStr = resultMap.at(AV_KEY_DURATION);
2199     int32_t duration = std::atoi(durationStr.c_str());
2200     if (!CheckMovingPhotoVideoDuration(duration)) {
2201         MEDIA_ERR_LOG("Failed to check duration of moving photo video: %{public}d ms", duration);
2202         return false;
2203     }
2204     return true;
2205 }
2206 
2207 std::string MediaFileUtils::GetTableNameByDisplayName(const std::string &displayName)
2208 {
2209     std::string extension;
2210     string::size_type currentPos = displayName.rfind('.');
2211     if (currentPos != std::string::npos) {
2212         extension = displayName.substr(currentPos + 1);
2213     }
2214 
2215     auto myTypeName = MimeTypeUtils::GetMimeTypeFromExtension(extension, MEDIA_MIME_TYPE_MAP);
2216     MediaType type = MimeTypeUtils::GetMediaTypeFromMimeType(myTypeName);
2217     if (type == MEDIA_TYPE_AUDIO) {
2218         return AudioColumn::AUDIOS_TABLE;
2219     } else if (type == MEDIA_TYPE_IMAGE || type == MEDIA_TYPE_VIDEO) {
2220         return PhotoColumn::PHOTOS_TABLE;
2221     }
2222     return "";
2223 }
2224 
2225 bool MediaFileUtils::GetDateModified(const string &path, int64_t &dateModified)
2226 {
2227     struct stat statInfo {};
2228     if (stat(path.c_str(), &statInfo) != E_OK) {
2229         MEDIA_ERR_LOG("stat error of %{private}s, errno: %{public}d", path.c_str(), errno);
2230         return false;
2231     }
2232     dateModified = Timespec2Millisecond(statInfo.st_mtim);
2233     return true;
2234 }
2235 
2236 bool MediaFileUtils::CheckMovingPhotoVideoDuration(int32_t duration)
2237 {
2238     // duration of moving photo video must be 0~10 s
2239     constexpr int32_t MIN_DURATION_MS = 0;
2240     constexpr int32_t MAX_DURATION_MS = 10000;
2241     return duration > MIN_DURATION_MS && duration <= MAX_DURATION_MS;
2242 }
2243 
2244 bool MediaFileUtils::CheckMovingPhotoEffectMode(int32_t effectMode)
2245 {
2246     return (effectMode >= static_cast<int32_t>(MovingPhotoEffectMode::EFFECT_MODE_START) &&
2247         effectMode <= static_cast<int32_t>(MovingPhotoEffectMode::EFFECT_MODE_END)) ||
2248         effectMode == static_cast<int32_t>(MovingPhotoEffectMode::IMAGE_ONLY);
2249 }
2250 
2251 bool MediaFileUtils::GetFileSize(const std::string& filePath, size_t& size)
2252 {
2253     struct stat statbuf;
2254     if (lstat(filePath.c_str(), &statbuf) == -1) {
2255         MEDIA_WARN_LOG("Failed to get file size, errno: %{public}d, path: %{private}s", errno, filePath.c_str());
2256         size = 0;
2257         return false;
2258     }
2259     if (statbuf.st_size < 0) {
2260         MEDIA_WARN_LOG("File size is negative, path: %{public}s", filePath.c_str());
2261         size = 0;
2262         return false;
2263     }
2264     size = static_cast<size_t>(statbuf.st_size);
2265     return true;
2266 }
2267 
2268 bool MediaFileUtils::SplitMovingPhotoUri(const std::string& uri, std::vector<std::string>& ret)
2269 {
2270     const std::string split(MOVING_PHOTO_URI_SPLIT);
2271     if (uri.empty() || IsMediaLibraryUri(uri)) {
2272         MEDIA_ERR_LOG("Failed to split moving photo uri, uri=%{public}s", uri.c_str());
2273         return false;
2274     }
2275     std::string temp = uri;
2276     size_t pos = temp.find(split);
2277     uint32_t step = split.size();
2278     ret.push_back(temp.substr(0, pos));
2279     ret.push_back(temp.substr(pos + step));
2280     return true;
2281 }
2282 
2283 bool MediaFileUtils::IsMediaLibraryUri(const std::string& uri)
2284 {
2285     return !uri.empty() && uri.find(MOVING_PHOTO_URI_SPLIT) == uri.npos;
2286 }
2287 
2288 void MediaFileUtils::CheckDirStatus(const std::unordered_set<std::string> &dirCheckSet, const std::string &dir)
2289 {
2290     if (dirCheckSet.count(dir) == 0) {
2291         return;
2292     }
2293     PrintStatInformation(dir);
2294 }
2295 
2296 int32_t MediaFileUtils::CreateDirectoryAndCopyFiles(const std::string &srcDir, const std::string &dstDir)
2297 {
2298     if (!MediaFileUtils::IsFileExists(srcDir)) {
2299         MEDIA_WARN_LOG("%{public}s doesn't exist, skip.", srcDir.c_str());
2300         return E_OK;
2301     }
2302     if (!MediaFileUtils::IsDirectory(srcDir)) {
2303         MEDIA_WARN_LOG("%{public}s is not an directory, skip.", srcDir.c_str());
2304         return E_OK;
2305     }
2306     if (!MediaFileUtils::CreateDirectory(dstDir)) {
2307         MEDIA_ERR_LOG("Create dstDir %{public}s failed", dstDir.c_str());
2308         return E_FAIL;
2309     }
2310     for (const auto &dirEntry : std::filesystem::directory_iterator{srcDir}) {
2311         std::string srcFilePath = dirEntry.path();
2312         std::string tmpFilePath = srcFilePath;
2313         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
2314         if (!MediaFileUtils::CopyFileUtil(srcFilePath, dstFilePath)) {
2315             MEDIA_ERR_LOG("Copy file from %{public}s to %{public}s failed.",
2316                 srcFilePath.c_str(),
2317                 dstFilePath.c_str());
2318             return E_FAIL;
2319         }
2320     }
2321     return E_OK;
2322 }
2323 
2324 void MediaFileUtils::ModifyFile(const std::string path, int64_t modifiedTime)
2325 {
2326     if (modifiedTime <= 0) {
2327         MEDIA_ERR_LOG("ModifyTime error!");
2328         return;
2329     }
2330     struct utimbuf buf;
2331     buf.actime = modifiedTime; // second
2332     buf.modtime = modifiedTime; // second
2333     int ret = utime(path.c_str(), &buf);
2334     if (ret != 0) {
2335         MEDIA_ERR_LOG("Modify file failed: %{public}d", ret);
2336     }
2337 }
2338 
2339 bool MediaFileUtils::CheckSupportedWatermarkType(int32_t watermarkType)
2340 {
2341     return watermarkType >= static_cast<int32_t>(WatermarkType::BRAND_COMMON) &&
2342         watermarkType <= static_cast<int32_t>(WatermarkType::BRAND);
2343 }
2344 
2345 int32_t MediaFileUtils::CopyDirectory(const std::string &srcDir, const std::string &dstDir)
2346 {
2347     if (srcDir.empty() || dstDir.empty()) {
2348         MEDIA_ERR_LOG("Failed to copy directory, srcDir:%{public}s or newPath:%{public}s is empty!",
2349             DesensitizePath(srcDir).c_str(), DesensitizePath(dstDir).c_str());
2350         return E_MODIFY_DATA_FAIL;
2351     }
2352     if (!IsFileExists(srcDir)) {
2353         MEDIA_ERR_LOG("SrcDir:%{public}s is not exist", DesensitizePath(srcDir).c_str());
2354         return E_NO_SUCH_FILE;
2355     }
2356     if (!IsDirectory(srcDir)) {
2357         MEDIA_ERR_LOG("SrcDir:%{public}s is not directory", DesensitizePath(srcDir).c_str());
2358         return E_FAIL;
2359     }
2360     if (IsFileExists(dstDir)) {
2361         MEDIA_ERR_LOG("DstDir:%{public}s exists", DesensitizePath(dstDir).c_str());
2362         return E_FILE_EXIST;
2363     }
2364     if (!CreateDirectory(dstDir)) {
2365         MEDIA_ERR_LOG("Create dstDir:%{public}s failed", DesensitizePath(dstDir).c_str());
2366         return E_FAIL;
2367     }
2368 
2369     for (const auto& entry : std::filesystem::recursive_directory_iterator(srcDir)) {
2370         std::string srcFilePath = entry.path();
2371         std::string tmpFilePath = srcFilePath;
2372         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
2373         if (entry.is_directory()) {
2374             if (!CreateDirectory(dstFilePath)) {
2375                 MEDIA_ERR_LOG("Create dir:%{public}s failed", DesensitizePath(dstFilePath).c_str());
2376                 return E_FAIL;
2377             }
2378         } else if (entry.is_regular_file()) {
2379             if (!CopyFileUtil(srcFilePath, dstFilePath)) {
2380                 MEDIA_ERR_LOG("Copy file from %{public}s to %{public}s failed.",
2381                     DesensitizePath(srcFilePath).c_str(), DesensitizePath(dstFilePath).c_str());
2382                 return E_FAIL;
2383             }
2384         } else {
2385             MEDIA_ERR_LOG("Unhandled path type, path:%{public}s", DesensitizePath(srcFilePath).c_str());
2386             return E_FAIL;
2387         }
2388     }
2389     return E_OK;
2390 }
2391 
2392 bool MediaFileUtils::IsCalledBySelf()
2393 {
2394     if (IPCSkeleton::GetCallingFullTokenID() == IPCSkeleton::GetSelfTokenID()) {
2395         return E_OK;
2396     }
2397     return E_FAIL;
2398 }
2399 
2400 bool MediaFileUtils::GenerateKvStoreKey(const std::string &fileId, const std::string &dateKey, std::string &key)
2401 {
2402     if (fileId.empty() || dateKey.empty()) {
2403         MEDIA_ERR_LOG("FileId:%{public}s or dateKey:%{public}s is empty", fileId.c_str(), dateKey.c_str());
2404         return false;
2405     }
2406 
2407     if (fileId.length() > KVSTORE_FILE_ID_TEMPLATE.length() ||
2408         dateKey.length() > KVSTORE_DATE_KEY_TEMPLATE.length()) {
2409         MEDIA_ERR_LOG("FileId:%{public}s or dateKey:%{public}s is too long", fileId.c_str(), dateKey.c_str());
2410         return false;
2411     }
2412     key = KVSTORE_DATE_KEY_TEMPLATE.substr(dateKey.length()) + dateKey +
2413           KVSTORE_FILE_ID_TEMPLATE.substr(fileId.length()) + fileId;
2414     return true;
2415 }
2416 
2417 bool MediaFileUtils::IsValidInteger(const std::string &value)
2418 {
2419     MEDIA_DEBUG_LOG("KeyWord is:%{public}s", value.c_str());
2420     std::string unsignedStr = value;
2421     while (unsignedStr.size() > 0 && unsignedStr[0] == '-') {
2422         unsignedStr = unsignedStr.substr(1);
2423     }
2424     for (size_t i = 0; i < unsignedStr.size(); i++) {
2425         if (!std::isdigit(unsignedStr[i])) {
2426             MEDIA_INFO_LOG("KeyWord invalid char of:%{public}c", unsignedStr[i]);
2427             unsignedStr = unsignedStr.substr(0, i);
2428             break;
2429         }
2430     }
2431     if (unsignedStr.size() == 0) {
2432         MEDIA_ERR_LOG("KeyWord Invalid argument");
2433         return false;
2434     } else if (unsignedStr.size() < INTEGER_MAX_LENGTH) {
2435         return true;
2436     } else if (unsignedStr.size() == INTEGER_MAX_LENGTH) {
2437         return unsignedStr < MAX_INTEGER;
2438     } else {
2439         MEDIA_ERR_LOG("KeyWord is out length!");
2440         return false;
2441     }
2442 }
2443 
2444 static int64_t GetRoundSize(int64_t size)
2445 {
2446     uint64_t val = 1;
2447     int64_t multple = UNIT;
2448     int64_t stdMultiple = STD_UNIT;
2449     while (static_cast<int64_t>(val) * stdMultiple < size) {
2450         val <<= 1;
2451         if (val > THRESHOLD) {
2452             val = 1;
2453             multple *= UNIT;
2454             stdMultiple *= STD_UNIT;
2455         }
2456     }
2457     return static_cast<int64_t>(val) * multple;
2458 }
2459 
2460 int64_t MediaFileUtils::GetTotalSize()
2461 {
2462     struct statvfs diskInfo;
2463     int ret = statvfs(DATA_PATH.c_str(), &diskInfo);
2464     CHECK_AND_RETURN_RET_LOG(ret == 0, E_ERR, "Get total size failed, errno:%{public}d", errno);
2465     int64_t totalSize = static_cast<long long>(diskInfo.f_bsize) * static_cast<long long>(diskInfo.f_blocks);
2466     CHECK_AND_RETURN_RET_LOG(totalSize > 0, E_ERR, "Get total size failed, totalSize:%{public}" PRId64, totalSize);
2467     totalSize = GetRoundSize(totalSize);
2468     return totalSize;
2469 }
2470 
2471 int64_t MediaFileUtils::GetFreeSize()
2472 {
2473     struct statvfs diskInfo;
2474     int ret = statvfs(DATA_PATH.c_str(), &diskInfo);
2475     CHECK_AND_RETURN_RET_LOG(ret == 0, E_ERR, "Get free size failed, errno:%{public}d", errno);
2476     int64_t freeSize = static_cast<int64_t>(diskInfo.f_bsize) * static_cast<int64_t>(diskInfo.f_bfree);
2477     return freeSize;
2478 }
2479 
2480 void MediaFileUtils::StatDirSize(const std::string& rootPath, size_t& totalSize)
2481 {
2482     std::stack<std::string> dirStack;
2483     dirStack.push(rootPath);
2484 
2485     while (!dirStack.empty()) {
2486         std::string currentPath = dirStack.top();
2487         dirStack.pop();
2488 
2489         DIR* dir = opendir(currentPath.c_str());
2490         if (dir == nullptr) {
2491             MEDIA_ERR_LOG("Failed to open directory.");
2492             continue;
2493         }
2494 
2495         struct dirent* entry;
2496         while ((entry = readdir(dir)) != nullptr) {
2497             if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
2498                 continue;
2499             }
2500 
2501             std::string fullPath = currentPath + "/" + entry->d_name;
2502             struct stat statBuf;
2503             if (stat(fullPath.c_str(), &statBuf) == -1) {
2504                 MEDIA_ERR_LOG("Failed to get file status.");
2505                 continue;
2506             }
2507 
2508             if (S_ISDIR(statBuf.st_mode)) {
2509                 dirStack.push(fullPath);
2510             } else if (S_ISREG(statBuf.st_mode)) {
2511                 size_t fileSize = 0;
2512                 MediaFileUtils::GetFileSize(fullPath, fileSize);
2513                 totalSize += fileSize;
2514             }
2515         }
2516 
2517         closedir(dir);
2518     }
2519 
2520     MEDIA_INFO_LOG("Directory size: %{public}lld bytes", static_cast<long long>(totalSize));
2521 }
2522 
2523 std::string MediaFileUtils::GetMimeTypeFromDisplayName(const std::string &displayName)
2524 {
2525     std::string mimeType = "";
2526     CHECK_AND_RETURN_RET_LOG(!displayName.empty(), mimeType, "displayName is empty.");
2527     std::string extension;
2528     string::size_type currentPos = displayName.rfind('.');
2529     if (currentPos != std::string::npos) {
2530         extension = displayName.substr(currentPos + 1);
2531     }
2532     CHECK_AND_RETURN_RET_LOG(!extension.empty(), mimeType, "extension is empty.");
2533     mimeType = MimeTypeUtils::GetMimeTypeFromExtension(extension, MEDIA_MIME_TYPE_MAP);
2534     return mimeType;
2535 }
2536 
2537 std::string MediaFileUtils::DesensitizeUri(const std::string &fileUri)
2538 {
2539     string result = fileUri;
2540     size_t slashIndex = result.rfind('/');
2541     CHECK_AND_RETURN_RET(slashIndex != std::string::npos, result);
2542     return result.replace(slashIndex + 1, result.length() - slashIndex - 1, "*");
2543 }
2544 
2545 bool MediaFileUtils::DeleteFileOrFolder(const std::string &path, bool isFile)
2546 {
2547     CHECK_AND_RETURN_RET(MediaFileUtils::IsFileExists(path), true);
2548     return isFile ? MediaFileUtils::DeleteFile(path) : MediaFileUtils::DeleteDir(path);
2549 }
2550 
2551 std::string MediaFileUtils::GetReplacedPathByPrefix(const std::string srcPrefix, const std::string dstPrefix,
2552     const std::string &path)
2553 {
2554     std::string replacedPath = path;
2555     replacedPath.replace(0, srcPrefix.length(), dstPrefix);
2556     return replacedPath;
2557 }
2558 
2559 int64_t MediaFileUtils::GetFileModificationTime(const std::string &path)
2560 {
2561     struct stat fileStat;
2562 
2563     if (stat(path.c_str(), &fileStat) == -1) {
2564         MEDIA_ERR_LOG("stat failed. File path: %{public}s, err: %{public}s", path.c_str(), strerror(errno));
2565         return 0;
2566     }
2567     struct tm* timeInfo = localtime(&fileStat.st_mtime);
2568     if (timeInfo == nullptr) {
2569         return 0;
2570     }
2571     return static_cast<int64_t>(fileStat.st_mtime);
2572 }
2573 
2574 bool MediaFileUtils::IsDirExists(const std::string &path)
2575 {
2576     struct stat st;
2577     if (stat(path.c_str(), &st) == 0) {
2578         return S_ISDIR(st.st_mode);
2579     }
2580     return false;
2581 }
2582 
2583 int64_t MediaFileUtils::StrToInt64(const std::string &value)
2584 {
2585     char* pEnd = nullptr;
2586     errno = 0;
2587     // check whether convert success
2588     int64_t res = std::strtoll(value.c_str(), &pEnd, 10);
2589     if (errno == ERANGE || pEnd == value.c_str() || *pEnd != '\0') {
2590         MEDIA_ERR_LOG("%{public}s:convert err.", __func__);
2591         return 0;
2592     }
2593     return res;
2594 }
2595 } // namespace OHOS::Media