13f4cbf05Sopenharmony_ci/*
23f4cbf05Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License.
53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at
63f4cbf05Sopenharmony_ci *
73f4cbf05Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83f4cbf05Sopenharmony_ci *
93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and
133f4cbf05Sopenharmony_ci * limitations under the License.
143f4cbf05Sopenharmony_ci */
153f4cbf05Sopenharmony_ci
163f4cbf05Sopenharmony_ci#include "directory_ex.h"
173f4cbf05Sopenharmony_ci#include <dirent.h>
183f4cbf05Sopenharmony_ci#include <cerrno>
193f4cbf05Sopenharmony_ci#include <fcntl.h>
203f4cbf05Sopenharmony_ci#include <stack>
213f4cbf05Sopenharmony_ci#include "securec.h"
223f4cbf05Sopenharmony_ci#include "unistd.h"
233f4cbf05Sopenharmony_ci#include "utils_log.h"
243f4cbf05Sopenharmony_ciusing namespace std;
253f4cbf05Sopenharmony_ci
263f4cbf05Sopenharmony_cinamespace OHOS {
273f4cbf05Sopenharmony_ci
283f4cbf05Sopenharmony_ci#ifdef UTILS_CXX_RUST
293f4cbf05Sopenharmony_cirust::String RustGetCurrentProcFullFileName()
303f4cbf05Sopenharmony_ci{
313f4cbf05Sopenharmony_ci    return rust::String(GetCurrentProcFullFileName());
323f4cbf05Sopenharmony_ci}
333f4cbf05Sopenharmony_ci
343f4cbf05Sopenharmony_cirust::String RustGetCurrentProcPath()
353f4cbf05Sopenharmony_ci{
363f4cbf05Sopenharmony_ci    return rust::String(GetCurrentProcPath());
373f4cbf05Sopenharmony_ci}
383f4cbf05Sopenharmony_ci
393f4cbf05Sopenharmony_cirust::String RustExtractFilePath(const rust::String& fileFullName)
403f4cbf05Sopenharmony_ci{
413f4cbf05Sopenharmony_ci    std::string tmpName = std::string(fileFullName);
423f4cbf05Sopenharmony_ci    return rust::String(ExtractFilePath(tmpName));
433f4cbf05Sopenharmony_ci}
443f4cbf05Sopenharmony_ci
453f4cbf05Sopenharmony_cirust::String RustExtractFileName(const rust::String& fileFullName)
463f4cbf05Sopenharmony_ci{
473f4cbf05Sopenharmony_ci    std::string tmpName = std::string(fileFullName);
483f4cbf05Sopenharmony_ci    return rust::String(ExtractFileName(tmpName));
493f4cbf05Sopenharmony_ci}
503f4cbf05Sopenharmony_ci
513f4cbf05Sopenharmony_cirust::String RustExtractFileExt(const rust::String& fileName)
523f4cbf05Sopenharmony_ci{
533f4cbf05Sopenharmony_ci    std::string tmpName = std::string(fileName);
543f4cbf05Sopenharmony_ci    return rust::String(ExtractFileExt(tmpName));
553f4cbf05Sopenharmony_ci}
563f4cbf05Sopenharmony_ci
573f4cbf05Sopenharmony_cirust::String RustExcludeTrailingPathDelimiter(const rust::String& path)
583f4cbf05Sopenharmony_ci{
593f4cbf05Sopenharmony_ci    std::string tmpPath = std::string(path);
603f4cbf05Sopenharmony_ci    return rust::String(ExcludeTrailingPathDelimiter(tmpPath));
613f4cbf05Sopenharmony_ci}
623f4cbf05Sopenharmony_ci
633f4cbf05Sopenharmony_cirust::String RustIncludeTrailingPathDelimiter(const rust::String& path)
643f4cbf05Sopenharmony_ci{
653f4cbf05Sopenharmony_ci    std::string tmpPath = std::string(path);
663f4cbf05Sopenharmony_ci    return rust::String(IncludeTrailingPathDelimiter(tmpPath));
673f4cbf05Sopenharmony_ci}
683f4cbf05Sopenharmony_ci
693f4cbf05Sopenharmony_cibool RustPathToRealPath(const rust::String& path, rust::String& realPath)
703f4cbf05Sopenharmony_ci{
713f4cbf05Sopenharmony_ci    std::string tmpPath = std::string(path);
723f4cbf05Sopenharmony_ci    std::string tmpResolved;
733f4cbf05Sopenharmony_ci
743f4cbf05Sopenharmony_ci    if (PathToRealPath(tmpPath, tmpResolved)) {
753f4cbf05Sopenharmony_ci        realPath = tmpResolved;
763f4cbf05Sopenharmony_ci        return true;
773f4cbf05Sopenharmony_ci    }
783f4cbf05Sopenharmony_ci
793f4cbf05Sopenharmony_ci    return false;
803f4cbf05Sopenharmony_ci}
813f4cbf05Sopenharmony_ci
823f4cbf05Sopenharmony_civoid RustGetDirFiles(const rust::String& path, rust::vec<rust::String>& files)
833f4cbf05Sopenharmony_ci{
843f4cbf05Sopenharmony_ci    std::string tmpPath(path);
853f4cbf05Sopenharmony_ci    std::vector<std::string> tmpFiles(files.begin(), files.end());
863f4cbf05Sopenharmony_ci    GetDirFiles(tmpPath, tmpFiles);
873f4cbf05Sopenharmony_ci    std::copy(tmpFiles.begin(), tmpFiles.end(), std::back_inserter(files));
883f4cbf05Sopenharmony_ci}
893f4cbf05Sopenharmony_ci#endif
903f4cbf05Sopenharmony_ci
913f4cbf05Sopenharmony_cistring GetCurrentProcFullFileName()
923f4cbf05Sopenharmony_ci{
933f4cbf05Sopenharmony_ci    char procFile[PATH_MAX + 1] = {0};
943f4cbf05Sopenharmony_ci    int ret = readlink("/proc/self/exe", procFile, PATH_MAX);
953f4cbf05Sopenharmony_ci    if (ret < 0 || ret > PATH_MAX) {
963f4cbf05Sopenharmony_ci        UTILS_LOGD("Get proc name failed, ret is: %{public}d!", ret);
973f4cbf05Sopenharmony_ci        return string();
983f4cbf05Sopenharmony_ci    }
993f4cbf05Sopenharmony_ci    procFile[ret] = '\0';
1003f4cbf05Sopenharmony_ci    return string(procFile);
1013f4cbf05Sopenharmony_ci}
1023f4cbf05Sopenharmony_ci
1033f4cbf05Sopenharmony_cistring GetCurrentProcPath()
1043f4cbf05Sopenharmony_ci{
1053f4cbf05Sopenharmony_ci    return ExtractFilePath(GetCurrentProcFullFileName());
1063f4cbf05Sopenharmony_ci}
1073f4cbf05Sopenharmony_ci
1083f4cbf05Sopenharmony_cistring ExtractFilePath(const string& fileFullName)
1093f4cbf05Sopenharmony_ci{
1103f4cbf05Sopenharmony_ci    return string(fileFullName).substr(0, fileFullName.rfind("/") + 1);
1113f4cbf05Sopenharmony_ci}
1123f4cbf05Sopenharmony_ci
1133f4cbf05Sopenharmony_cistd::string ExtractFileName(const std::string& fileFullName)
1143f4cbf05Sopenharmony_ci{
1153f4cbf05Sopenharmony_ci    return string(fileFullName).substr(fileFullName.rfind("/") + 1, fileFullName.size());
1163f4cbf05Sopenharmony_ci}
1173f4cbf05Sopenharmony_ci
1183f4cbf05Sopenharmony_cistring ExtractFileExt(const string& fileName)
1193f4cbf05Sopenharmony_ci{
1203f4cbf05Sopenharmony_ci    string::size_type pos = fileName.rfind(".");
1213f4cbf05Sopenharmony_ci    if (pos == string::npos) {
1223f4cbf05Sopenharmony_ci        return "";
1233f4cbf05Sopenharmony_ci    }
1243f4cbf05Sopenharmony_ci
1253f4cbf05Sopenharmony_ci    return string(fileName).substr(pos + 1, fileName.size());
1263f4cbf05Sopenharmony_ci}
1273f4cbf05Sopenharmony_ci
1283f4cbf05Sopenharmony_cistring ExcludeTrailingPathDelimiter(const std::string& path)
1293f4cbf05Sopenharmony_ci{
1303f4cbf05Sopenharmony_ci    if (path.rfind("/") != path.size() - 1) {
1313f4cbf05Sopenharmony_ci        return path;
1323f4cbf05Sopenharmony_ci    }
1333f4cbf05Sopenharmony_ci
1343f4cbf05Sopenharmony_ci    if (!path.empty()) {
1353f4cbf05Sopenharmony_ci        return path.substr(0, (int)path.size() - 1);
1363f4cbf05Sopenharmony_ci    }
1373f4cbf05Sopenharmony_ci
1383f4cbf05Sopenharmony_ci    return path;
1393f4cbf05Sopenharmony_ci}
1403f4cbf05Sopenharmony_ci
1413f4cbf05Sopenharmony_cistring IncludeTrailingPathDelimiter(const std::string& path)
1423f4cbf05Sopenharmony_ci{
1433f4cbf05Sopenharmony_ci    if (path.empty()) {
1443f4cbf05Sopenharmony_ci        return  "/";
1453f4cbf05Sopenharmony_ci    }
1463f4cbf05Sopenharmony_ci    if (path.rfind("/") != path.size() - 1) {
1473f4cbf05Sopenharmony_ci        return path + "/";
1483f4cbf05Sopenharmony_ci    }
1493f4cbf05Sopenharmony_ci
1503f4cbf05Sopenharmony_ci    return path;
1513f4cbf05Sopenharmony_ci}
1523f4cbf05Sopenharmony_ci
1533f4cbf05Sopenharmony_civoid GetDirFiles(const string& path, vector<string>& files)
1543f4cbf05Sopenharmony_ci{
1553f4cbf05Sopenharmony_ci    DIR *dir = opendir(path.c_str());
1563f4cbf05Sopenharmony_ci    if (dir == nullptr) {
1573f4cbf05Sopenharmony_ci        UTILS_LOGD("Failed to open root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno));
1583f4cbf05Sopenharmony_ci        return;
1593f4cbf05Sopenharmony_ci    }
1603f4cbf05Sopenharmony_ci
1613f4cbf05Sopenharmony_ci    string currentPath = ExcludeTrailingPathDelimiter(path);
1623f4cbf05Sopenharmony_ci    stack<DIR *> traverseStack;
1633f4cbf05Sopenharmony_ci    traverseStack.push(dir);
1643f4cbf05Sopenharmony_ci    while (!traverseStack.empty()) {
1653f4cbf05Sopenharmony_ci        DIR *topNode = traverseStack.top();
1663f4cbf05Sopenharmony_ci        dirent *ptr = readdir(topNode);
1673f4cbf05Sopenharmony_ci        if (ptr == nullptr) {
1683f4cbf05Sopenharmony_ci            closedir(topNode);
1693f4cbf05Sopenharmony_ci            traverseStack.pop();
1703f4cbf05Sopenharmony_ci            auto pos = currentPath.find_last_of("/");
1713f4cbf05Sopenharmony_ci            if (pos != string::npos) {
1723f4cbf05Sopenharmony_ci                currentPath.erase(pos);
1733f4cbf05Sopenharmony_ci            }
1743f4cbf05Sopenharmony_ci            continue;
1753f4cbf05Sopenharmony_ci        }
1763f4cbf05Sopenharmony_ci
1773f4cbf05Sopenharmony_ci        string name = ptr->d_name;
1783f4cbf05Sopenharmony_ci        if (name == "." || name == "..") {
1793f4cbf05Sopenharmony_ci            continue;
1803f4cbf05Sopenharmony_ci        }
1813f4cbf05Sopenharmony_ci        if (ptr->d_type == DT_DIR) {
1823f4cbf05Sopenharmony_ci            int currentFd = dirfd(topNode);
1833f4cbf05Sopenharmony_ci            if (currentFd < 0) {
1843f4cbf05Sopenharmony_ci                UTILS_LOGD("Failed to get dirfd, fd: %{public}d: %{public}s ", currentFd, strerror(errno));
1853f4cbf05Sopenharmony_ci                continue;
1863f4cbf05Sopenharmony_ci            }
1873f4cbf05Sopenharmony_ci            int subFd = openat(currentFd, name.c_str(), O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
1883f4cbf05Sopenharmony_ci            if (subFd < 0) {
1893f4cbf05Sopenharmony_ci                UTILS_LOGD("Failed in subFd openat: %{public}s ", name.c_str());
1903f4cbf05Sopenharmony_ci                continue;
1913f4cbf05Sopenharmony_ci            }
1923f4cbf05Sopenharmony_ci            DIR *subDir = fdopendir(subFd);
1933f4cbf05Sopenharmony_ci            if (subDir == nullptr) {
1943f4cbf05Sopenharmony_ci                close(subFd);
1953f4cbf05Sopenharmony_ci                UTILS_LOGD("Failed in fdopendir: %{public}s", strerror(errno));
1963f4cbf05Sopenharmony_ci                continue;
1973f4cbf05Sopenharmony_ci            }
1983f4cbf05Sopenharmony_ci            traverseStack.push(subDir);
1993f4cbf05Sopenharmony_ci            currentPath = IncludeTrailingPathDelimiter(currentPath) + name;
2003f4cbf05Sopenharmony_ci        } else {
2013f4cbf05Sopenharmony_ci            files.push_back(IncludeTrailingPathDelimiter(currentPath) + name);
2023f4cbf05Sopenharmony_ci        }
2033f4cbf05Sopenharmony_ci    }
2043f4cbf05Sopenharmony_ci}
2053f4cbf05Sopenharmony_ci
2063f4cbf05Sopenharmony_cibool ForceCreateDirectory(const string& path)
2073f4cbf05Sopenharmony_ci{
2083f4cbf05Sopenharmony_ci    string::size_type index = 0;
2093f4cbf05Sopenharmony_ci    do {
2103f4cbf05Sopenharmony_ci        string subPath;
2113f4cbf05Sopenharmony_ci        index = path.find('/', index + 1);
2123f4cbf05Sopenharmony_ci        if (index == string::npos) {
2133f4cbf05Sopenharmony_ci            subPath = path;
2143f4cbf05Sopenharmony_ci        } else {
2153f4cbf05Sopenharmony_ci            subPath = path.substr(0, index);
2163f4cbf05Sopenharmony_ci        }
2173f4cbf05Sopenharmony_ci
2183f4cbf05Sopenharmony_ci        if (access(subPath.c_str(), F_OK) != 0) {
2193f4cbf05Sopenharmony_ci            if (mkdir(subPath.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) {
2203f4cbf05Sopenharmony_ci                return false;
2213f4cbf05Sopenharmony_ci            }
2223f4cbf05Sopenharmony_ci        }
2233f4cbf05Sopenharmony_ci    } while (index != string::npos);
2243f4cbf05Sopenharmony_ci
2253f4cbf05Sopenharmony_ci    return access(path.c_str(), F_OK) == 0;
2263f4cbf05Sopenharmony_ci}
2273f4cbf05Sopenharmony_ci
2283f4cbf05Sopenharmony_cistruct DirectoryNode {
2293f4cbf05Sopenharmony_ci    DIR *dir;
2303f4cbf05Sopenharmony_ci    int currentFd;
2313f4cbf05Sopenharmony_ci    char name[256]; // the same max char length with d_name in struct dirent
2323f4cbf05Sopenharmony_ci};
2333f4cbf05Sopenharmony_ci
2343f4cbf05Sopenharmony_cibool ForceRemoveDirectory(const string& path)
2353f4cbf05Sopenharmony_ci{
2363f4cbf05Sopenharmony_ci    bool ret = true;
2373f4cbf05Sopenharmony_ci    int strRet;
2383f4cbf05Sopenharmony_ci    DIR *dir = opendir(path.c_str());
2393f4cbf05Sopenharmony_ci    if (dir == nullptr) {
2403f4cbf05Sopenharmony_ci        UTILS_LOGE("Failed to open root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno));
2413f4cbf05Sopenharmony_ci        return false;
2423f4cbf05Sopenharmony_ci    }
2433f4cbf05Sopenharmony_ci    stack<DIR *> traversStack;
2443f4cbf05Sopenharmony_ci    stack<DirectoryNode> removeStack;
2453f4cbf05Sopenharmony_ci    traversStack.push(dir);
2463f4cbf05Sopenharmony_ci    while (!traversStack.empty()) {
2473f4cbf05Sopenharmony_ci        DIR *currentDir = traversStack.top();
2483f4cbf05Sopenharmony_ci        traversStack.pop();
2493f4cbf05Sopenharmony_ci        DirectoryNode node;
2503f4cbf05Sopenharmony_ci        int currentFd = dirfd(currentDir);
2513f4cbf05Sopenharmony_ci        if (currentFd < 0) {
2523f4cbf05Sopenharmony_ci            UTILS_LOGE("Failed to get dirfd, fd: %{public}d: %{public}s ", currentFd, strerror(errno));
2533f4cbf05Sopenharmony_ci            ret = false;
2543f4cbf05Sopenharmony_ci            continue;
2553f4cbf05Sopenharmony_ci        }
2563f4cbf05Sopenharmony_ci
2573f4cbf05Sopenharmony_ci        while (true) {
2583f4cbf05Sopenharmony_ci            struct dirent *ptr = readdir(currentDir);
2593f4cbf05Sopenharmony_ci            if (ptr == nullptr) {
2603f4cbf05Sopenharmony_ci                break;
2613f4cbf05Sopenharmony_ci            }
2623f4cbf05Sopenharmony_ci            const char *name = ptr->d_name;
2633f4cbf05Sopenharmony_ci            // current dir or parent dir
2643f4cbf05Sopenharmony_ci            if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
2653f4cbf05Sopenharmony_ci                continue;
2663f4cbf05Sopenharmony_ci            }
2673f4cbf05Sopenharmony_ci
2683f4cbf05Sopenharmony_ci            if (ptr->d_type == DT_DIR) {
2693f4cbf05Sopenharmony_ci                int subFd = openat(currentFd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
2703f4cbf05Sopenharmony_ci                if (subFd < 0) {
2713f4cbf05Sopenharmony_ci                    UTILS_LOGE("Failed in subFd openat: %{public}s ", name);
2723f4cbf05Sopenharmony_ci                    ret = false;
2733f4cbf05Sopenharmony_ci                    continue;
2743f4cbf05Sopenharmony_ci                }
2753f4cbf05Sopenharmony_ci                DIR *subDir = fdopendir(subFd);
2763f4cbf05Sopenharmony_ci                if (subDir == nullptr) {
2773f4cbf05Sopenharmony_ci                    close(subFd);
2783f4cbf05Sopenharmony_ci                    UTILS_LOGE("Failed in fdopendir: %{public}s", strerror(errno));
2793f4cbf05Sopenharmony_ci                    ret = false;
2803f4cbf05Sopenharmony_ci                    continue;
2813f4cbf05Sopenharmony_ci                }
2823f4cbf05Sopenharmony_ci                node.dir = subDir;
2833f4cbf05Sopenharmony_ci                node.currentFd = currentFd;
2843f4cbf05Sopenharmony_ci                strRet = strcpy_s(node.name, sizeof(node.name), name);
2853f4cbf05Sopenharmony_ci                if (strRet != EOK) {
2863f4cbf05Sopenharmony_ci                    UTILS_LOGE("Failed to exec strcpy_s, name= %{public}s, strRet= %{public}d", name, strRet);
2873f4cbf05Sopenharmony_ci                }
2883f4cbf05Sopenharmony_ci                removeStack.push(node);
2893f4cbf05Sopenharmony_ci                traversStack.push(subDir);
2903f4cbf05Sopenharmony_ci            } else {
2913f4cbf05Sopenharmony_ci                if (faccessat(currentFd, name, F_OK, AT_SYMLINK_NOFOLLOW) == 0) {
2923f4cbf05Sopenharmony_ci                    if (unlinkat(currentFd, name, 0) < 0) {
2933f4cbf05Sopenharmony_ci                        UTILS_LOGE("Couldn't unlinkat subFile %{public}s: %{public}s", name, strerror(errno));
2943f4cbf05Sopenharmony_ci                        ret = false;
2953f4cbf05Sopenharmony_ci                        break;
2963f4cbf05Sopenharmony_ci                    }
2973f4cbf05Sopenharmony_ci                } else {
2983f4cbf05Sopenharmony_ci                    UTILS_LOGE("Access to file: %{public}s is failed", name);
2993f4cbf05Sopenharmony_ci                    ret = false;
3003f4cbf05Sopenharmony_ci                    break;
3013f4cbf05Sopenharmony_ci                }
3023f4cbf05Sopenharmony_ci            }
3033f4cbf05Sopenharmony_ci        }
3043f4cbf05Sopenharmony_ci    }
3053f4cbf05Sopenharmony_ci    if (!ret) {
3063f4cbf05Sopenharmony_ci        UTILS_LOGD("Failed to remove some subfile under path: %{public}s", path.c_str());
3073f4cbf05Sopenharmony_ci    }
3083f4cbf05Sopenharmony_ci    while (!removeStack.empty()) {
3093f4cbf05Sopenharmony_ci        DirectoryNode node = removeStack.top();
3103f4cbf05Sopenharmony_ci        removeStack.pop();
3113f4cbf05Sopenharmony_ci        closedir(node.dir);
3123f4cbf05Sopenharmony_ci        if (unlinkat(node.currentFd, node.name, AT_REMOVEDIR) < 0) {
3133f4cbf05Sopenharmony_ci            UTILS_LOGE("Couldn't unlinkat subDir %{public}s: %{public}s", node.name, strerror(errno));
3143f4cbf05Sopenharmony_ci            continue;
3153f4cbf05Sopenharmony_ci        }
3163f4cbf05Sopenharmony_ci    }
3173f4cbf05Sopenharmony_ci    closedir(dir);
3183f4cbf05Sopenharmony_ci    if (faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) == 0) {
3193f4cbf05Sopenharmony_ci        if (remove(path.c_str()) != 0) {
3203f4cbf05Sopenharmony_ci            UTILS_LOGE("Failed to remove root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno));
3213f4cbf05Sopenharmony_ci            return false;
3223f4cbf05Sopenharmony_ci        }
3233f4cbf05Sopenharmony_ci    }
3243f4cbf05Sopenharmony_ci    return faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) != 0;
3253f4cbf05Sopenharmony_ci}
3263f4cbf05Sopenharmony_ci
3273f4cbf05Sopenharmony_cibool RemoveFile(const string& fileName)
3283f4cbf05Sopenharmony_ci{
3293f4cbf05Sopenharmony_ci    if (access(fileName.c_str(), F_OK) == 0) {
3303f4cbf05Sopenharmony_ci        return remove(fileName.c_str()) == 0;
3313f4cbf05Sopenharmony_ci    }
3323f4cbf05Sopenharmony_ci
3333f4cbf05Sopenharmony_ci    return true;
3343f4cbf05Sopenharmony_ci}
3353f4cbf05Sopenharmony_ci
3363f4cbf05Sopenharmony_cibool IsEmptyFolder(const string& path)
3373f4cbf05Sopenharmony_ci{
3383f4cbf05Sopenharmony_ci    vector<string> files;
3393f4cbf05Sopenharmony_ci    GetDirFiles(path, files);
3403f4cbf05Sopenharmony_ci    return files.empty();
3413f4cbf05Sopenharmony_ci}
3423f4cbf05Sopenharmony_ci
3433f4cbf05Sopenharmony_ciuint64_t GetFolderSize(const string& path)
3443f4cbf05Sopenharmony_ci{
3453f4cbf05Sopenharmony_ci    vector<string> files;
3463f4cbf05Sopenharmony_ci    struct stat statbuf = {0};
3473f4cbf05Sopenharmony_ci    GetDirFiles(path, files);
3483f4cbf05Sopenharmony_ci    uint64_t totalSize = 0;
3493f4cbf05Sopenharmony_ci    for (auto& file : files) {
3503f4cbf05Sopenharmony_ci        if (stat(file.c_str(), &statbuf) == 0) {
3513f4cbf05Sopenharmony_ci            totalSize += statbuf.st_size;
3523f4cbf05Sopenharmony_ci        }
3533f4cbf05Sopenharmony_ci    }
3543f4cbf05Sopenharmony_ci
3553f4cbf05Sopenharmony_ci    return totalSize;
3563f4cbf05Sopenharmony_ci}
3573f4cbf05Sopenharmony_ci
3583f4cbf05Sopenharmony_ci// inner function, and param is legitimate
3593f4cbf05Sopenharmony_cibool ChangeMode(const string& fileName, const mode_t& mode)
3603f4cbf05Sopenharmony_ci{
3613f4cbf05Sopenharmony_ci    return (chmod(fileName.c_str(), mode) == 0);
3623f4cbf05Sopenharmony_ci}
3633f4cbf05Sopenharmony_ci
3643f4cbf05Sopenharmony_cibool ChangeModeFile(const string& fileName, const mode_t& mode)
3653f4cbf05Sopenharmony_ci{
3663f4cbf05Sopenharmony_ci    if (access(fileName.c_str(), F_OK) != 0) {
3673f4cbf05Sopenharmony_ci        return false;
3683f4cbf05Sopenharmony_ci    }
3693f4cbf05Sopenharmony_ci
3703f4cbf05Sopenharmony_ci    return ChangeMode(fileName, mode);
3713f4cbf05Sopenharmony_ci}
3723f4cbf05Sopenharmony_ci
3733f4cbf05Sopenharmony_cibool ChangeModeDirectory(const string& path, const mode_t& mode)
3743f4cbf05Sopenharmony_ci{
3753f4cbf05Sopenharmony_ci    string subPath;
3763f4cbf05Sopenharmony_ci    bool ret = true;
3773f4cbf05Sopenharmony_ci    DIR *dir = opendir(path.c_str());
3783f4cbf05Sopenharmony_ci    if (dir == nullptr) {
3793f4cbf05Sopenharmony_ci        return false;
3803f4cbf05Sopenharmony_ci    }
3813f4cbf05Sopenharmony_ci
3823f4cbf05Sopenharmony_ci    while (true) {
3833f4cbf05Sopenharmony_ci        struct dirent *ptr = readdir(dir);
3843f4cbf05Sopenharmony_ci        if (ptr == nullptr) {
3853f4cbf05Sopenharmony_ci            break;
3863f4cbf05Sopenharmony_ci        }
3873f4cbf05Sopenharmony_ci
3883f4cbf05Sopenharmony_ci        // current dir or parent dir
3893f4cbf05Sopenharmony_ci        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
3903f4cbf05Sopenharmony_ci            continue;
3913f4cbf05Sopenharmony_ci        }
3923f4cbf05Sopenharmony_ci        subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
3933f4cbf05Sopenharmony_ci        if (ptr->d_type == DT_DIR) {
3943f4cbf05Sopenharmony_ci            ret = ChangeModeDirectory(subPath, mode);
3953f4cbf05Sopenharmony_ci        } else {
3963f4cbf05Sopenharmony_ci            if (access(subPath.c_str(), F_OK) == 0) {
3973f4cbf05Sopenharmony_ci                if (!ChangeMode(subPath, mode)) {
3983f4cbf05Sopenharmony_ci                    UTILS_LOGD("Failed to exec ChangeMode");
3993f4cbf05Sopenharmony_ci                    closedir(dir);
4003f4cbf05Sopenharmony_ci                    return false;
4013f4cbf05Sopenharmony_ci                }
4023f4cbf05Sopenharmony_ci            }
4033f4cbf05Sopenharmony_ci        }
4043f4cbf05Sopenharmony_ci    }
4053f4cbf05Sopenharmony_ci    closedir(dir);
4063f4cbf05Sopenharmony_ci    string currentPath = ExcludeTrailingPathDelimiter(path);
4073f4cbf05Sopenharmony_ci    if (access(currentPath.c_str(), F_OK) == 0) {
4083f4cbf05Sopenharmony_ci        if (!ChangeMode(currentPath, mode)) {
4093f4cbf05Sopenharmony_ci            UTILS_LOGD("Failed to exec ChangeMode");
4103f4cbf05Sopenharmony_ci            return false;
4113f4cbf05Sopenharmony_ci        }
4123f4cbf05Sopenharmony_ci    }
4133f4cbf05Sopenharmony_ci    return ret;
4143f4cbf05Sopenharmony_ci}
4153f4cbf05Sopenharmony_ci
4163f4cbf05Sopenharmony_cibool PathToRealPath(const string& path, string& realPath)
4173f4cbf05Sopenharmony_ci{
4183f4cbf05Sopenharmony_ci    if (path.empty()) {
4193f4cbf05Sopenharmony_ci        UTILS_LOGD("path is empty!");
4203f4cbf05Sopenharmony_ci        return false;
4213f4cbf05Sopenharmony_ci    }
4223f4cbf05Sopenharmony_ci
4233f4cbf05Sopenharmony_ci    if ((path.length() >= PATH_MAX)) {
4243f4cbf05Sopenharmony_ci        UTILS_LOGD("path len is error, the len is: [%{public}zu]", path.length());
4253f4cbf05Sopenharmony_ci        return false;
4263f4cbf05Sopenharmony_ci    }
4273f4cbf05Sopenharmony_ci
4283f4cbf05Sopenharmony_ci    char tmpPath[PATH_MAX] = {0};
4293f4cbf05Sopenharmony_ci    if (realpath(path.c_str(), tmpPath) == nullptr) {
4303f4cbf05Sopenharmony_ci        UTILS_LOGE("path (%{public}s) to realpath error: %{public}s", path.c_str(), strerror(errno));
4313f4cbf05Sopenharmony_ci        return false;
4323f4cbf05Sopenharmony_ci    }
4333f4cbf05Sopenharmony_ci
4343f4cbf05Sopenharmony_ci    realPath = tmpPath;
4353f4cbf05Sopenharmony_ci    if (access(realPath.c_str(), F_OK) != 0) {
4363f4cbf05Sopenharmony_ci        UTILS_LOGE("check realpath (%{private}s) error: %{public}s", realPath.c_str(), strerror(errno));
4373f4cbf05Sopenharmony_ci        return false;
4383f4cbf05Sopenharmony_ci    }
4393f4cbf05Sopenharmony_ci    return true;
4403f4cbf05Sopenharmony_ci}
4413f4cbf05Sopenharmony_ci
4423f4cbf05Sopenharmony_ci#if defined(IOS_PLATFORM) || defined(_WIN32)
4433f4cbf05Sopenharmony_cistring TransformFileName(const string& fileName)
4443f4cbf05Sopenharmony_ci{
4453f4cbf05Sopenharmony_ci    string::size_type pos = fileName.find(".");
4463f4cbf05Sopenharmony_ci    string transformfileName = "";
4473f4cbf05Sopenharmony_ci    if (pos == string::npos) {
4483f4cbf05Sopenharmony_ci        transformfileName = fileName;
4493f4cbf05Sopenharmony_ci
4503f4cbf05Sopenharmony_ci#ifdef _WIN32
4513f4cbf05Sopenharmony_ci        transformfileName = transformfileName.append(".dll");
4523f4cbf05Sopenharmony_ci#elif defined IOS_PLATFORM
4533f4cbf05Sopenharmony_ci        transformfileName = transformfileName.append(".dylib");
4543f4cbf05Sopenharmony_ci#endif
4553f4cbf05Sopenharmony_ci
4563f4cbf05Sopenharmony_ci        return transformfileName;
4573f4cbf05Sopenharmony_ci    } else {
4583f4cbf05Sopenharmony_ci        transformfileName = string(fileName).substr(0, pos + 1);
4593f4cbf05Sopenharmony_ci
4603f4cbf05Sopenharmony_ci#ifdef _WIN32
4613f4cbf05Sopenharmony_ci        transformfileName = transformfileName.append("dll");
4623f4cbf05Sopenharmony_ci#elif defined IOS_PLATFORM
4633f4cbf05Sopenharmony_ci        transformfileName = transformfileName.append("dylib");
4643f4cbf05Sopenharmony_ci#endif
4653f4cbf05Sopenharmony_ci
4663f4cbf05Sopenharmony_ci        return transformfileName;
4673f4cbf05Sopenharmony_ci    }
4683f4cbf05Sopenharmony_ci}
4693f4cbf05Sopenharmony_ci#endif
4703f4cbf05Sopenharmony_ci
4713f4cbf05Sopenharmony_ci} // OHOS
472