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