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