• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "ringtone_file_utils.h"
18 
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <ftw.h>
22 #include <fstream>
23 #include <sstream>
24 #include <sys/sendfile.h>
25 #include <unistd.h>
26 #include <iostream>
27 
28 #include "directory_ex.h"
29 #include "ringtone_db_const.h"
30 #include "ringtone_errno.h"
31 #include "ringtone_log.h"
32 #include "ringtone_mimetype_utils.h"
33 #include "ringtone_type.h"
34 #include "securec.h"
35 
36 namespace OHOS {
37 namespace Media {
38 using namespace std;
39 static const int32_t OPEN_FDS = 128;
40 static const mode_t MODE_RWX_USR_GRP = 02771;
41 static const mode_t MODE_RW_USR = 0644;
42 const vector<string> EXIF_SUPPORTED_EXTENSION = {
43     RINGTONE_CONTAINER_TYPE_3GA,
44     RINGTONE_CONTAINER_TYPE_AC3,
45     RINGTONE_CONTAINER_TYPE_A52,
46     RINGTONE_CONTAINER_TYPE_AMR,
47     RINGTONE_CONTAINER_TYPE_IMY,
48     RINGTONE_CONTAINER_TYPE_RTTTL,
49     RINGTONE_CONTAINER_TYPE_XMF,
50     RINGTONE_CONTAINER_TYPE_RTX,
51     RINGTONE_CONTAINER_TYPE_MXMF,
52     RINGTONE_CONTAINER_TYPE_M4A,
53     RINGTONE_CONTAINER_TYPE_M4B,
54     RINGTONE_CONTAINER_TYPE_M4P,
55     RINGTONE_CONTAINER_TYPE_F4A,
56     RINGTONE_CONTAINER_TYPE_F4B,
57     RINGTONE_CONTAINER_TYPE_F4P,
58     RINGTONE_CONTAINER_TYPE_M3U,
59     RINGTONE_CONTAINER_TYPE_SMF,
60     RINGTONE_CONTAINER_TYPE_MKA,
61     RINGTONE_CONTAINER_TYPE_RA,
62     RINGTONE_CONTAINER_TYPE_MP3,
63     RINGTONE_CONTAINER_TYPE_AAC,
64     RINGTONE_CONTAINER_TYPE_ADTS,
65     RINGTONE_CONTAINER_TYPE_ADT,
66     RINGTONE_CONTAINER_TYPE_SND,
67     RINGTONE_CONTAINER_TYPE_FLAC,
68     RINGTONE_CONTAINER_TYPE_MP2,
69     RINGTONE_CONTAINER_TYPE_MP1,
70     RINGTONE_CONTAINER_TYPE_MPA,
71     RINGTONE_CONTAINER_TYPE_M4R,
72     RINGTONE_CONTAINER_TYPE_WAV,
73     RINGTONE_CONTAINER_TYPE_OGG
74 };
75 
IsTargetExtension(const string & path)76 static bool IsTargetExtension(const string &path)
77 {
78     const string ext = RingtoneFileUtils::GetExtensionFromPath(path);
79     std::string mimeType = RingtoneMimeTypeUtils::GetMimeTypeFromExtension(ext);
80     int32_t mime = RingtoneMimeTypeUtils::GetMediaTypeFromMimeType(mimeType);
81     if (mime == RINGTONE_MEDIA_TYPE_AUDIO) {
82         return true;
83     }
84     RINGTONE_ERR_LOG("MimeType error:%{public}s,%{public}s", ext.c_str(), mimeType.c_str());
85     bool ret = find(EXIF_SUPPORTED_EXTENSION.begin(), EXIF_SUPPORTED_EXTENSION.end(), ext) !=
86         EXIF_SUPPORTED_EXTENSION.end();
87     if (!ret) {
88         RINGTONE_ERR_LOG("invalid target extension:%{public}s", ext.c_str());
89     }
90     return ret;
91 }
92 
SplitByChar(const string & str,const char split)93 string RingtoneFileUtils::SplitByChar(const string &str, const char split)
94 {
95     size_t splitIndex = str.find_last_of(split);
96     return (splitIndex == string::npos) ? ("") : (str.substr(splitIndex + 1));
97 }
98 
GetExtensionFromPath(const string & path)99 string RingtoneFileUtils::GetExtensionFromPath(const string &path)
100 {
101     string extention = SplitByChar(path, '.');
102     if (!extention.empty()) {
103         transform(extention.begin(), extention.end(), extention.begin(), ::tolower);
104     }
105     return extention;
106 }
107 
GetFileNameFromPath(const string & path)108 string RingtoneFileUtils::GetFileNameFromPath(const string &path)
109 {
110     string fileName = {};
111     size_t found = path.rfind("/");
112     if (found != string::npos && (found + 1) < path.size()) {
113         fileName = path.substr(found + 1);
114     } else {
115         fileName = "";
116     }
117 
118     return fileName;
119 }
120 
ParseFromUri(const string & path,const string & key)121 static string ParseFromUri(const string& path, const string& key)
122 {
123     RINGTONE_INFO_LOG("parsing uri : %{public}s for key : %{public}s", path.c_str(), key.c_str());
124     auto keyLen = key.size();
125     auto found = path.find(key);
126     if (found == string::npos) {
127         RINGTONE_INFO_LOG("there is no such field in uri: %{public}s", path.c_str());
128         return "";
129     }
130     string sub = path.substr(found + keyLen + 1);
131     found = sub.find("&");
132     if (found != string::npos) {
133         sub = sub.substr(0, found);
134     }
135     sub = RingtoneFileUtils::UrlDecode(sub);
136     RINGTONE_INFO_LOG("parsing uri : %{public}s -> key=%{public}s, value=%{public}s",
137         path.c_str(), key.c_str(), sub.c_str());
138     return sub;
139 }
140 
GetFileNameFromPathOrUri(const string & path,bool & isTitle)141 string RingtoneFileUtils::GetFileNameFromPathOrUri(const string &path, bool &isTitle)
142 {
143     string fileName = {};
144     size_t found = path.find("content://");
145     if (found == 0) {
146         fileName = ParseFromUri(path, "title"); // Pay attention! It's actually "title".
147         isTitle = true;
148     } else {
149         fileName = GetFileNameFromPath(path);
150         isTitle = false;
151     }
152     RINGTONE_INFO_LOG("%{public}s -> %{public}s", path.c_str(), fileName.c_str());
153     return fileName;
154 }
155 
GetBaseNameFromPath(const string & path)156 string RingtoneFileUtils::GetBaseNameFromPath(const string &path)
157 {
158     size_t found = path.rfind("/");
159     size_t foundDot = path.rfind(".");
160 
161     string baseName = {};
162     found = (found == string::npos ? 0 : found);
163     if ((foundDot > found) && (foundDot != string::npos)) {
164         baseName = path.substr(found + 1, foundDot - found - 1);
165     } else {
166         baseName = "";
167     }
168 
169     return baseName;
170 }
171 
IsSameFile(const string & srcPath,const string & dstPath)172 bool RingtoneFileUtils::IsSameFile(const string &srcPath, const string &dstPath)
173 {
174     struct stat srcStatInfo {};
175     struct stat dstStatInfo {};
176 
177     if (access(srcPath.c_str(), F_OK) || access(dstPath.c_str(), F_OK)) {
178         return false;
179     }
180     if (stat(srcPath.c_str(), &srcStatInfo) != 0) {
181         RINGTONE_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", srcPath.c_str(), errno);
182         return false;
183     }
184     if (stat(dstPath.c_str(), &dstStatInfo) != 0) {
185         RINGTONE_ERR_LOG("Failed to get file %{private}s StatInfo, err=%{public}d", dstPath.c_str(), errno);
186         return false;
187     }
188     if (srcStatInfo.st_size != dstStatInfo.st_size) { /* file size */
189         RINGTONE_INFO_LOG("Size differs, srcStatInfo.st_size != dstStatInfo.st_size");
190         return false;
191     }
192 
193     return true;
194 }
195 
UnlinkCb(const char * fpath,const struct stat * sb,int32_t typeflag,struct FTW * ftwbuf)196 static int32_t UnlinkCb(const char *fpath, const struct stat *sb, int32_t typeflag, struct FTW *ftwbuf)
197 {
198     CHECK_AND_RETURN_RET_LOG(fpath != nullptr, E_FAIL, "fpath == nullptr");
199     int32_t errRet = remove(fpath);
200     if (errRet) {
201         RINGTONE_ERR_LOG("Failed to remove errno: %{public}d, path: %{private}s", errno, fpath);
202     }
203 
204     return errRet;
205 }
206 
RemoveDirectory(const string & path)207 int32_t RingtoneFileUtils::RemoveDirectory(const string &path)
208 {
209     return nftw(path.c_str(), UnlinkCb, OPEN_FDS, FTW_DEPTH | FTW_PHYS);
210 }
211 
Mkdir(const string & subStr,shared_ptr<int> errCodePtr)212 bool RingtoneFileUtils::Mkdir(const string &subStr, shared_ptr<int> errCodePtr)
213 {
214     mode_t mask = umask(0);
215     if (mkdir(subStr.c_str(), MODE_RWX_USR_GRP) == -1) {
216         if (errCodePtr != nullptr) {
217             *errCodePtr = errno;
218         }
219         RINGTONE_ERR_LOG("Failed to create directory %{public}d", errno);
220         umask(mask);
221         return (errno == EEXIST) ? true : false;
222     }
223     umask(mask);
224     return true;
225 }
226 
IsDirectory(const string & dirName,shared_ptr<int> errCodePtr)227 bool RingtoneFileUtils::IsDirectory(const string &dirName, shared_ptr<int> errCodePtr)
228 {
229     struct stat statInfo {};
230 
231     if (stat(dirName.c_str(), &statInfo) == 0) {
232         if (statInfo.st_mode & S_IFDIR) {
233             return true;
234         }
235     } else if (errCodePtr != nullptr) {
236         *errCodePtr = errno;
237         return false;
238     }
239 
240     return false;
241 }
242 
CreateDirectory(const string & dirPath,shared_ptr<int> errCodePtr)243 bool RingtoneFileUtils::CreateDirectory(const string &dirPath, shared_ptr<int> errCodePtr)
244 {
245     string subStr;
246     string segment;
247 
248     stringstream folderStream(dirPath);
249     while (getline(folderStream, segment, '/')) {
250         if (segment.empty()) {
251             continue;
252         }
253 
254         subStr.append(RINGTONE_SLASH_CHAR + segment);
255         if (!IsDirectory(subStr, errCodePtr)) {
256             if (!Mkdir(subStr, errCodePtr)) {
257                 return false;
258             }
259         }
260     }
261     return true;
262 }
263 
OpenFile(const string & filePath,const string & mode)264 int32_t RingtoneFileUtils::OpenFile(const string &filePath, const string &mode)
265 {
266     int32_t errCode = E_ERR;
267 
268     if (filePath.empty() || mode.empty()) {
269         RINGTONE_ERR_LOG("Invalid open argument! mode: %{private}s, path: %{private}s", mode.c_str(), filePath.c_str());
270         return errCode;
271     }
272 
273     if (!IsTargetExtension(filePath)) {
274         return E_INVALID_PATH;
275     }
276 
277     static const unordered_map<string, int32_t> RINGTONE_OPEN_MODE_MAP = {
278         { RINGTONE_FILEMODE_READONLY, O_RDONLY },
279         { RINGTONE_FILEMODE_WRITEONLY, O_WRONLY },
280         { RINGTONE_FILEMODE_READWRITE, O_RDWR },
281         { RINGTONE_FILEMODE_WRITETRUNCATE, O_WRONLY | O_TRUNC },
282         { RINGTONE_FILEMODE_WRITEAPPEND, O_WRONLY | O_APPEND },
283         { RINGTONE_FILEMODE_READWRITETRUNCATE, O_RDWR | O_TRUNC },
284         { RINGTONE_FILEMODE_READWRITEAPPEND, O_RDWR | O_APPEND },
285     };
286     if (RINGTONE_OPEN_MODE_MAP.find(mode) == RINGTONE_OPEN_MODE_MAP.end()) {
287         return E_ERR;
288     }
289 
290     if (filePath.size() >= PATH_MAX) {
291         RINGTONE_ERR_LOG("File path too long %{public}d", (int)filePath.size());
292         return errCode;
293     }
294     string absFilePath;
295     if (!PathToRealPath(filePath, absFilePath)) {
296         RINGTONE_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
297         return errCode;
298     }
299     if (absFilePath.empty()) {
300         RINGTONE_ERR_LOG("Failed to obtain the canonical path for source path %{public}d %{private}s",
301             errno, filePath.c_str());
302         return errCode;
303     }
304     RINGTONE_INFO_LOG("File absFilePath is %{private}s", absFilePath.c_str());
305     return open(absFilePath.c_str(), RINGTONE_OPEN_MODE_MAP.at(mode));
306 }
307 
IsFileExists(const string & fileName)308 bool RingtoneFileUtils::IsFileExists(const string &fileName)
309 {
310     struct stat statInfo {};
311 
312     return ((stat(fileName.c_str(), &statInfo)) == 0);
313 }
314 
CreateFile(const string & filePath)315 int32_t RingtoneFileUtils::CreateFile(const string &filePath)
316 {
317     int32_t errCode = E_ERR;
318 
319     if (filePath.empty()) {
320         RINGTONE_ERR_LOG("Filepath is empty");
321         return E_VIOLATION_PARAMETERS;
322     }
323 
324     if (!IsTargetExtension(filePath)) {
325         return E_INVALID_PATH;
326     }
327 
328     if (IsFileExists(filePath)) {
329         RINGTONE_ERR_LOG("the file exists path: %{private}s", filePath.c_str());
330         return E_FILE_EXIST;
331     }
332 
333     ofstream file(filePath);
334     if (!file) {
335         RINGTONE_ERR_LOG("Output file path could not be created errno %{public}d", errno);
336         return errCode;
337     }
338 
339     file.close();
340 
341     return E_SUCCESS;
342 }
343 
DeleteFile(const string & fileName)344 bool RingtoneFileUtils::DeleteFile(const string &fileName)
345 {
346     return (remove(fileName.c_str()) == 0);
347 }
348 
MoveFile(const string & oldPath,const string & newPath)349 bool RingtoneFileUtils::MoveFile(const string &oldPath, const string &newPath)
350 {
351     bool errRet = false;
352 
353     if (IsFileExists(oldPath) && !IsFileExists(newPath)) {
354         errRet = (rename(oldPath.c_str(), newPath.c_str()) == 0);
355     }
356 
357     return errRet;
358 }
359 
CopyFileUtil(const string & filePath,const string & newPath)360 bool RingtoneFileUtils::CopyFileUtil(const string &filePath, const string &newPath)
361 {
362     struct stat fst{};
363     bool ret = false;
364     if (filePath.size() >= PATH_MAX) {
365         RINGTONE_ERR_LOG("File path too long %{public}d", static_cast<int>(filePath.size()));
366         return ret;
367     }
368     RINGTONE_INFO_LOG("File path is %{private}s", filePath.c_str());
369     string absFilePath;
370     if (!PathToRealPath(filePath, absFilePath)) {
371         RINGTONE_ERR_LOG("file is not real path, file path: %{private}s", filePath.c_str());
372         return ret;
373     }
374     if (absFilePath.empty()) {
375         RINGTONE_ERR_LOG("Failed to obtain the canonical path for source path%{private}s %{public}d",
376             filePath.c_str(), errno);
377         return ret;
378     }
379 
380     int32_t source = open(absFilePath.c_str(), O_RDONLY);
381     if (source == -1) {
382         RINGTONE_ERR_LOG("Open failed for source file");
383         return ret;
384     }
385 
386     int32_t dest = open(newPath.c_str(), O_WRONLY | O_CREAT, MODE_RW_USR);
387     if (dest == -1) {
388         RINGTONE_ERR_LOG("Open failed for destination file %{public}d", errno);
389         close(source);
390         return ret;
391     }
392 
393     if (fstat(source, &fst) == 0) {
394         // Copy file content
395         if (sendfile(dest, source, nullptr, fst.st_size) != E_ERR) {
396             // Copy ownership and mode of source file
397             if (fchown(dest, fst.st_uid, fst.st_gid) == 0 &&
398                 fchmod(dest, fst.st_mode) == 0) {
399                 ret= true;
400             }
401         }
402     }
403 
404     close(source);
405     close(dest);
406 
407     return ret;
408 }
409 
Timespec2Millisecond(const struct timespec & time)410 int64_t RingtoneFileUtils::Timespec2Millisecond(const struct timespec &time)
411 {
412     return time.tv_sec * MSEC_TO_SEC + time.tv_nsec / MSEC_TO_NSEC;
413 }
414 
StartsWith(const string & str,const string & prefix)415 bool RingtoneFileUtils::StartsWith(const string &str, const string &prefix)
416 {
417     return str.compare(0, prefix.size(), prefix) == 0;
418 }
419 
UTCTimeMilliSeconds()420 int64_t RingtoneFileUtils::UTCTimeMilliSeconds()
421 {
422     struct timespec t;
423     clock_gettime(CLOCK_REALTIME, &t);
424     return t.tv_sec * MSEC_TO_SEC + t.tv_nsec / MSEC_TO_NSEC;
425 }
426 
UTCTimeSeconds()427 int64_t RingtoneFileUtils::UTCTimeSeconds()
428 {
429     struct timespec t{};
430     t.tv_sec = 0;
431     t.tv_nsec = 0;
432     clock_gettime(CLOCK_REALTIME, &t);
433     return (int64_t)(t.tv_sec);
434 }
435 
StrCreateTimeByMilliseconds(const string & format,int64_t time)436 string RingtoneFileUtils::StrCreateTimeByMilliseconds(const string &format, int64_t time)
437 {
438     char strTime[DEFAULT_TIME_SIZE] = "";
439     int64_t times = time / MSEC_TO_SEC;
440     auto tm = localtime(&times);
441     if (tm == nullptr) {
442         return "";
443     }
444     (void)strftime(strTime, sizeof(strTime), format.c_str(), tm);
445     return strTime;
446 }
447 
448 static const int URL_DECODE_DOUBLE = 2;
UrlDecode(const string & src)449 string RingtoneFileUtils::UrlDecode(const string &src)
450 {
451     string ret;
452     char ch;
453     int tmpNum;
454     for (size_t i = 0; i < src.length(); i++) {
455         if (src[i]=='%') {
456             if (sscanf_s(src.substr(i + 1, URL_DECODE_DOUBLE).c_str(), "%x", &tmpNum) == -1) {
457                 RINGTONE_ERR_LOG("Not a valid url: %{private}s", src.c_str());
458                 return src;
459             }
460             ch = static_cast<char>(tmpNum);
461             ret += ch;
462             i = i + URL_DECODE_DOUBLE;
463         } else {
464             ret += src[i];
465         }
466     }
467     return ret;
468 }
469 
MkdirRecursive(const string & path,size_t start)470 static int32_t MkdirRecursive(const string &path, size_t start)
471 {
472     RINGTONE_DEBUG_LOG("start pos %{public}zu", start);
473     size_t end = path.find("/", start + 1);
474 
475     string subDir = "";
476     if (end == std::string::npos) {
477         if (start + 1 == path.size()) {
478             RINGTONE_DEBUG_LOG("path size=%zu", path.size());
479         } else {
480             subDir = path.substr(start + 1, path.size() - start - 1);
481         }
482     } else {
483         subDir = path.substr(start + 1, end - start - 1);
484     }
485 
486     if (subDir.size() == 0) {
487         return E_SUCCESS;
488     } else {
489         string real = path.substr(0, start + subDir.size() + 1);
490         mode_t mask = umask(0);
491         int result = mkdir(real.c_str(), MODE_RWX_USR_GRP);
492         if (result == 0) {
493             RINGTONE_INFO_LOG("mkdir %{public}s successfully", real.c_str());
494         } else {
495             RINGTONE_INFO_LOG("mkdir %{public}s failed, errno is %{public}d", real.c_str(), errno);
496         }
497         umask(mask);
498     }
499     if (end == std::string::npos) {
500         return E_SUCCESS;
501     }
502 
503     return MkdirRecursive(path, end);
504 }
505 
CreatePreloadFolder(const string & path)506 int32_t RingtoneFileUtils::CreatePreloadFolder(const string &path)
507 {
508     RINGTONE_DEBUG_LOG("start");
509     if (access(path.c_str(), F_OK) == 0) {
510         RINGTONE_DEBUG_LOG("dir is existing");
511         return E_SUCCESS;
512     }
513 
514     auto start = path.find(RINGTONE_CUSTOMIZED_BASE_PATH);
515     if (start == string::npos) {
516         RINGTONE_ERR_LOG("base dir is wrong");
517         return E_ERR;
518     }
519 
520     return MkdirRecursive(path, start + RINGTONE_CUSTOMIZED_BASE_PATH.size());
521 }
522 
CreateRingtoneDir()523 void RingtoneFileUtils::CreateRingtoneDir()
524 {
525     static const vector<string> userPreloadDirs = {
526         { RINGTONE_CUSTOMIZED_ALARM_PATH }, { RINGTONE_CUSTOMIZED_RINGTONE_PATH },
527         { RINGTONE_CUSTOMIZED_NOTIFICATIONS_PATH }
528     };
529 
530     for (const auto &dir: userPreloadDirs) {
531         if (CreatePreloadFolder(dir) != E_SUCCESS) {
532             RINGTONE_INFO_LOG("scan failed on dir %{public}s", dir.c_str());
533             continue;
534         }
535     }
536 }
537 
MoveDirectory(const std::string & srcDir,const std::string & dstDir)538 int32_t RingtoneFileUtils::MoveDirectory(const std::string &srcDir, const std::string &dstDir)
539 {
540     if (access(srcDir.c_str(), F_OK) != 0) {
541         RINGTONE_ERR_LOG("access srcDir failed, errno is %{public}d", errno);
542         return E_FAIL;
543     }
544     if (access(dstDir.c_str(), F_OK) != 0) {
545         RINGTONE_ERR_LOG("access dstDir failed, errno is %{public}d", errno);
546         return E_FAIL;
547     }
548     int ret = E_SUCCESS;
549     for (const auto &dirEntry : std::filesystem::directory_iterator{ srcDir }) {
550         std::string srcFilePath = dirEntry.path();
551         std::string tmpFilePath = srcFilePath;
552         std::string dstFilePath = tmpFilePath.replace(0, srcDir.length(), dstDir);
553         if (!MoveFile(srcFilePath, dstFilePath)) {
554             RINGTONE_ERR_LOG("Move file failed, errno is %{public}d", errno);
555             ret = E_FAIL;
556         }
557     }
558     return ret;
559 }
560 
AccessRingtoneDir()561 void RingtoneFileUtils::AccessRingtoneDir()
562 {
563     if (access(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str(), F_OK) != 0) {
564         CreateRingtoneDir();
565         return;
566     }
567     struct stat fileStat;
568     if (stat(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str(), &fileStat) != 0) {
569         RINGTONE_ERR_LOG("stat dir failed, errno is %{public}d", errno);
570         return;
571     }
572     // 检查组的写权限
573     if ((fileStat.st_mode & S_IWGRP) != 0) {
574         return;
575     }
576     if (IsEmptyFolder(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str())) {
577         RINGTONE_ERR_LOG("The directory is empty and lacks group write permission.");
578         if (DeleteFile(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str())) {
579             RINGTONE_ERR_LOG("DeleteFile denied, errCode: %{public}d", errno);
580         }
581         CreateRingtoneDir();
582     } else { //rename and move file
583         RINGTONE_ERR_LOG("The directory is not empty and lacks group write permission.");
584         if (MoveFile(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str(),
585             RINGTONE_CUSTOMIZED_BASE_RINGTONETMP_PATH.c_str())) {
586             if (CreatePreloadFolder(RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str()) != E_SUCCESS) {
587                 RINGTONE_ERR_LOG("Create Ringtone dir failed, errno is %{public}d", errno);
588                 //restore dir
589                 MoveFile(RINGTONE_CUSTOMIZED_BASE_RINGTONETMP_PATH.c_str(),
590                     RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str());
591                 return;
592             }
593             if (MoveDirectory(RINGTONE_CUSTOMIZED_BASE_RINGTONETMP_PATH.c_str(),
594                 RINGTONE_CUSTOMIZED_BASE_RINGTONE_PATH.c_str()) != E_SUCCESS) {
595                 RINGTONE_ERR_LOG("Move dir failed, errno is %{public}d", errno);
596                 CreateRingtoneDir();
597                 return;
598             }
599             if (DeleteFile(RINGTONE_CUSTOMIZED_BASE_RINGTONETMP_PATH.c_str())) {
600                 RINGTONE_ERR_LOG("DeleteFile denied, errCode: %{public}d", errno);
601             }
602         } else {
603             RINGTONE_ERR_LOG("Move Ringtone dir failed, errno is %{public}d", errno);
604         }
605     }
606     return;
607 }
608 
GetFileExtension(const string & path)609 string RingtoneFileUtils::GetFileExtension(const string &path)
610 {
611     if (!path.empty()) {
612         size_t dotIndex = path.rfind(".");
613         if (dotIndex != string::npos) {
614             return path.substr(dotIndex + 1);
615         }
616     }
617 
618     RINGTONE_ERR_LOG("Failed to obtain file extension because given pathname is empty");
619     return "";
620 }
621 } // namespace Media
622 } // namespace OHOS
623