17405867cSopenharmony_ci/*
27405867cSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
37405867cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47405867cSopenharmony_ci * you may not use this file except in compliance with the License.
57405867cSopenharmony_ci * You may obtain a copy of the License at
67405867cSopenharmony_ci *
77405867cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87405867cSopenharmony_ci *
97405867cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107405867cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117405867cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127405867cSopenharmony_ci * See the License for the specific language governing permissions and
137405867cSopenharmony_ci * limitations under the License.
147405867cSopenharmony_ci */
157405867cSopenharmony_ci#include "file_util.h"
167405867cSopenharmony_ci
177405867cSopenharmony_ci#include <dirent.h>
187405867cSopenharmony_ci#include <fstream>
197405867cSopenharmony_ci#include <iostream>
207405867cSopenharmony_ci#include <sys/stat.h>
217405867cSopenharmony_ci#include <sys/types.h>
227405867cSopenharmony_ci#include <sys/xattr.h>
237405867cSopenharmony_ci#include <unistd.h>
247405867cSopenharmony_ci
257405867cSopenharmony_cinamespace OHOS {
267405867cSopenharmony_cinamespace HiviewDFX {
277405867cSopenharmony_cinamespace FileUtil {
287405867cSopenharmony_cinamespace {
297405867cSopenharmony_ciconst char PATH_DELIMITER = '/';
307405867cSopenharmony_ciconstexpr mode_t FILE_PERM_600 = S_IRUSR | S_IWUSR;
317405867cSopenharmony_ci}
327405867cSopenharmony_cibool IsFileExists(const std::string& file)
337405867cSopenharmony_ci{
347405867cSopenharmony_ci    return access(file.c_str(), F_OK) == 0;
357405867cSopenharmony_ci}
367405867cSopenharmony_ci
377405867cSopenharmony_cibool IsFile(const std::string& file)
387405867cSopenharmony_ci{
397405867cSopenharmony_ci    struct stat statBuf {};
407405867cSopenharmony_ci    return lstat(file.c_str(), &statBuf) == 0 ? S_ISREG(statBuf.st_mode) : false;
417405867cSopenharmony_ci}
427405867cSopenharmony_ci
437405867cSopenharmony_cibool IsDirectory(const std::string& dir)
447405867cSopenharmony_ci{
457405867cSopenharmony_ci    struct stat statBuf {};
467405867cSopenharmony_ci    return lstat(dir.c_str(), &statBuf) == 0 ? S_ISDIR(statBuf.st_mode) : false;
477405867cSopenharmony_ci}
487405867cSopenharmony_ci
497405867cSopenharmony_cibool RemoveFile(const std::string& file)
507405867cSopenharmony_ci{
517405867cSopenharmony_ci    return !IsFileExists(file) || (remove(file.c_str()) == 0);
527405867cSopenharmony_ci}
537405867cSopenharmony_ci
547405867cSopenharmony_cibool RemoveDirectory(const std::string& dir)
557405867cSopenharmony_ci{
567405867cSopenharmony_ci    return !IsFileExists(dir) || (rmdir(dir.c_str()) == 0);
577405867cSopenharmony_ci}
587405867cSopenharmony_ci
597405867cSopenharmony_cibool ForceCreateDirectory(const std::string& dir)
607405867cSopenharmony_ci{
617405867cSopenharmony_ci    std::string::size_type index = 0;
627405867cSopenharmony_ci    do {
637405867cSopenharmony_ci        std::string subPath;
647405867cSopenharmony_ci        index = dir.find('/', index + 1); // (index + 1) means the next char traversed
657405867cSopenharmony_ci        if (index == std::string::npos) {
667405867cSopenharmony_ci            subPath = dir;
677405867cSopenharmony_ci        } else {
687405867cSopenharmony_ci            subPath = dir.substr(0, index);
697405867cSopenharmony_ci        }
707405867cSopenharmony_ci
717405867cSopenharmony_ci        if (!IsFileExists(subPath) && mkdir(subPath.c_str(), S_IRWXU) != 0) {
727405867cSopenharmony_ci            return false;
737405867cSopenharmony_ci        }
747405867cSopenharmony_ci    } while (index != std::string::npos);
757405867cSopenharmony_ci    return IsFileExists(dir);
767405867cSopenharmony_ci}
777405867cSopenharmony_ci
787405867cSopenharmony_cibool ForceRemoveDirectory(const std::string& dir, bool isDeleteSelf)
797405867cSopenharmony_ci{
807405867cSopenharmony_ci    if (IsFile(dir)) {
817405867cSopenharmony_ci        return RemoveFile(dir);
827405867cSopenharmony_ci    } else if (IsDirectory(dir)) {
837405867cSopenharmony_ci        DIR* dirPtr = opendir(dir.c_str());
847405867cSopenharmony_ci        if (dirPtr == nullptr) {
857405867cSopenharmony_ci            return false;
867405867cSopenharmony_ci        }
877405867cSopenharmony_ci        struct dirent* dirInfo = nullptr;
887405867cSopenharmony_ci        while ((dirInfo = readdir(dirPtr)) != nullptr) {
897405867cSopenharmony_ci            // do not process the special dir
907405867cSopenharmony_ci            if (strcmp(dirInfo->d_name, ".") == 0 || strcmp(dirInfo->d_name, "..") == 0) {
917405867cSopenharmony_ci                continue;
927405867cSopenharmony_ci            }
937405867cSopenharmony_ci            std::string filePath = GetFilePathByDir(dir, dirInfo->d_name);
947405867cSopenharmony_ci            if (!ForceRemoveDirectory(filePath)) {
957405867cSopenharmony_ci                closedir(dirPtr);
967405867cSopenharmony_ci                return false;
977405867cSopenharmony_ci            }
987405867cSopenharmony_ci        }
997405867cSopenharmony_ci        closedir(dirPtr);
1007405867cSopenharmony_ci        if (isDeleteSelf && !RemoveDirectory(dir)) {
1017405867cSopenharmony_ci            return false;
1027405867cSopenharmony_ci        }
1037405867cSopenharmony_ci    } else {
1047405867cSopenharmony_ci        return false;
1057405867cSopenharmony_ci    }
1067405867cSopenharmony_ci    return true;
1077405867cSopenharmony_ci}
1087405867cSopenharmony_ci
1097405867cSopenharmony_civoid GetDirFiles(const std::string& dir, std::vector<std::string>& files)
1107405867cSopenharmony_ci{
1117405867cSopenharmony_ci    DIR* dirPtr = opendir(dir.c_str());
1127405867cSopenharmony_ci    if (dirPtr == nullptr) {
1137405867cSopenharmony_ci        return;
1147405867cSopenharmony_ci    }
1157405867cSopenharmony_ci
1167405867cSopenharmony_ci    struct dirent* ent = nullptr;
1177405867cSopenharmony_ci    while ((ent = readdir(dirPtr)) != nullptr) {
1187405867cSopenharmony_ci        if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
1197405867cSopenharmony_ci            continue;
1207405867cSopenharmony_ci        }
1217405867cSopenharmony_ci        std::string filePath = GetFilePathByDir(dir, ent->d_name);
1227405867cSopenharmony_ci        if (IsFile(filePath)) { // do not process subdirectory
1237405867cSopenharmony_ci            files.push_back(filePath);
1247405867cSopenharmony_ci        }
1257405867cSopenharmony_ci    }
1267405867cSopenharmony_ci    closedir(dirPtr);
1277405867cSopenharmony_ci}
1287405867cSopenharmony_ci
1297405867cSopenharmony_ciuint64_t GetDirSize(const std::string& dir)
1307405867cSopenharmony_ci{
1317405867cSopenharmony_ci    std::vector<std::string> files;
1327405867cSopenharmony_ci    GetDirFiles(dir, files);
1337405867cSopenharmony_ci    uint64_t totalSize = 0;
1347405867cSopenharmony_ci    struct stat statBuf {};
1357405867cSopenharmony_ci    for (auto& file : files) {
1367405867cSopenharmony_ci        if (stat(file.c_str(), &statBuf) == 0) {
1377405867cSopenharmony_ci            totalSize += static_cast<uint64_t>(statBuf.st_size);
1387405867cSopenharmony_ci        }
1397405867cSopenharmony_ci    }
1407405867cSopenharmony_ci    return totalSize;
1417405867cSopenharmony_ci}
1427405867cSopenharmony_ci
1437405867cSopenharmony_ciuint64_t GetFileSize(const std::string& file)
1447405867cSopenharmony_ci{
1457405867cSopenharmony_ci    struct stat statBuf {};
1467405867cSopenharmony_ci    return stat(file.c_str(), &statBuf) == 0 ? static_cast<uint64_t>(statBuf.st_size) : 0;
1477405867cSopenharmony_ci}
1487405867cSopenharmony_ci
1497405867cSopenharmony_cibool ChangeMode(const std::string& file, const mode_t& mode)
1507405867cSopenharmony_ci{
1517405867cSopenharmony_ci    return (chmod(file.c_str(), mode) == 0);
1527405867cSopenharmony_ci}
1537405867cSopenharmony_ci
1547405867cSopenharmony_cibool CreateFile(const std::string& file, const mode_t& mode)
1557405867cSopenharmony_ci{
1567405867cSopenharmony_ci    if (IsFileExists(file)) {
1577405867cSopenharmony_ci        return true;
1587405867cSopenharmony_ci    }
1597405867cSopenharmony_ci    std::ofstream fout(file);
1607405867cSopenharmony_ci    if (!fout.is_open()) {
1617405867cSopenharmony_ci        return false;
1627405867cSopenharmony_ci    }
1637405867cSopenharmony_ci    fout.flush();
1647405867cSopenharmony_ci    fout.close();
1657405867cSopenharmony_ci    return ChangeMode(file, mode);
1667405867cSopenharmony_ci}
1677405867cSopenharmony_ci
1687405867cSopenharmony_cibool SaveStringToFile(const std::string& file, const std::string& content, bool isTrunc)
1697405867cSopenharmony_ci{
1707405867cSopenharmony_ci    if (content.empty()) {
1717405867cSopenharmony_ci        return true;
1727405867cSopenharmony_ci    }
1737405867cSopenharmony_ci
1747405867cSopenharmony_ci    if (!CreateFile(file, FILE_PERM_600)) {
1757405867cSopenharmony_ci        return false;
1767405867cSopenharmony_ci    }
1777405867cSopenharmony_ci    std::ofstream os;
1787405867cSopenharmony_ci    if (isTrunc) {
1797405867cSopenharmony_ci        os.open(file.c_str(), std::ios::out | std::ios::trunc);
1807405867cSopenharmony_ci    } else {
1817405867cSopenharmony_ci        os.open(file.c_str(), std::ios::out | std::ios::app);
1827405867cSopenharmony_ci    }
1837405867cSopenharmony_ci    if (!os.is_open()) {
1847405867cSopenharmony_ci        return false;
1857405867cSopenharmony_ci    }
1867405867cSopenharmony_ci
1877405867cSopenharmony_ci    os.write(content.c_str(), content.length());
1887405867cSopenharmony_ci    if (os.fail()) {
1897405867cSopenharmony_ci        os.close();
1907405867cSopenharmony_ci        return false;
1917405867cSopenharmony_ci    }
1927405867cSopenharmony_ci    os.close();
1937405867cSopenharmony_ci    return true;
1947405867cSopenharmony_ci}
1957405867cSopenharmony_ci
1967405867cSopenharmony_cistd::string GetFilePathByDir(const std::string& dir, const std::string& fileName)
1977405867cSopenharmony_ci{
1987405867cSopenharmony_ci    if (dir.empty()) {
1997405867cSopenharmony_ci        return fileName;
2007405867cSopenharmony_ci    }
2017405867cSopenharmony_ci    std::string filePath = dir;
2027405867cSopenharmony_ci    if (filePath.back() != '/') {
2037405867cSopenharmony_ci        filePath.push_back(PATH_DELIMITER);
2047405867cSopenharmony_ci    }
2057405867cSopenharmony_ci    filePath.append(fileName);
2067405867cSopenharmony_ci    return filePath;
2077405867cSopenharmony_ci}
2087405867cSopenharmony_ci
2097405867cSopenharmony_cibool LoadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines)
2107405867cSopenharmony_ci{
2117405867cSopenharmony_ci    std::ifstream file(filePath);
2127405867cSopenharmony_ci    if (file.is_open()) {
2137405867cSopenharmony_ci        std::string line;
2147405867cSopenharmony_ci        while (std::getline(file, line)) {
2157405867cSopenharmony_ci            lines.emplace_back(line);
2167405867cSopenharmony_ci        }
2177405867cSopenharmony_ci        file.close();
2187405867cSopenharmony_ci        return true;
2197405867cSopenharmony_ci    }
2207405867cSopenharmony_ci    return false;
2217405867cSopenharmony_ci}
2227405867cSopenharmony_ci
2237405867cSopenharmony_cibool SetDirXattr(const std::string& dir, const std::string& name, const std::string& value)
2247405867cSopenharmony_ci{
2257405867cSopenharmony_ci    return setxattr(dir.c_str(), name.c_str(), value.c_str(), strlen(value.c_str()), 0) == 0;
2267405867cSopenharmony_ci}
2277405867cSopenharmony_ci} // namespace FileUtil
2287405867cSopenharmony_ci} // namespace HiviewDFX
2297405867cSopenharmony_ci} // namespace OHOS
230