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