106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci *
1506f6ba60Sopenharmony_ci * Description: FileUtils implements
1606f6ba60Sopenharmony_ci */
1706f6ba60Sopenharmony_ci#include "file_utils.h"
1806f6ba60Sopenharmony_ci
1906f6ba60Sopenharmony_ci#include <cerrno>
2006f6ba60Sopenharmony_ci#include <cstring>
2106f6ba60Sopenharmony_ci#include <dirent.h>
2206f6ba60Sopenharmony_ci#include <fcntl.h>
2306f6ba60Sopenharmony_ci#include <unistd.h>
2406f6ba60Sopenharmony_ci#include <regex>
2506f6ba60Sopenharmony_ci#include "logging.h"
2606f6ba60Sopenharmony_ci
2706f6ba60Sopenharmony_cinamespace {
2806f6ba60Sopenharmony_ciconstexpr size_t DEFAULT_READ_SIZE = 4096;
2906f6ba60Sopenharmony_ci}
3006f6ba60Sopenharmony_ci
3106f6ba60Sopenharmony_cistd::string FileUtils::ReadFile(int fd)
3206f6ba60Sopenharmony_ci{
3306f6ba60Sopenharmony_ci    std::string content;
3406f6ba60Sopenharmony_ci    size_t count = 0;
3506f6ba60Sopenharmony_ci    while (true) {
3606f6ba60Sopenharmony_ci        if (content.size() - count < DEFAULT_READ_SIZE) {
3706f6ba60Sopenharmony_ci            content.resize(content.size() + DEFAULT_READ_SIZE);
3806f6ba60Sopenharmony_ci        }
3906f6ba60Sopenharmony_ci        ssize_t nBytes = TEMP_FAILURE_RETRY(read(fd, &content[count], content.size() - count));
4006f6ba60Sopenharmony_ci        if (nBytes == -1 && errno == EAGAIN) {
4106f6ba60Sopenharmony_ci            continue;
4206f6ba60Sopenharmony_ci        }
4306f6ba60Sopenharmony_ci        if (nBytes <= 0) {
4406f6ba60Sopenharmony_ci            break;
4506f6ba60Sopenharmony_ci        }
4606f6ba60Sopenharmony_ci        count += nBytes;
4706f6ba60Sopenharmony_ci    }
4806f6ba60Sopenharmony_ci    content.resize(count);
4906f6ba60Sopenharmony_ci    return content;
5006f6ba60Sopenharmony_ci}
5106f6ba60Sopenharmony_ci
5206f6ba60Sopenharmony_cistd::string FileUtils::ReadFile(const std::string& path)
5306f6ba60Sopenharmony_ci{
5406f6ba60Sopenharmony_ci    char realPath[PATH_MAX + 1] = {0};
5506f6ba60Sopenharmony_ci    CHECK_TRUE((path.length() < PATH_MAX) && (realpath(path.c_str(), realPath) != nullptr), "",
5606f6ba60Sopenharmony_ci               "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
5706f6ba60Sopenharmony_ci    int fd = open(realPath, O_RDONLY);
5806f6ba60Sopenharmony_ci    if (fd == -1) {
5906f6ba60Sopenharmony_ci        const int bufSize = 256;
6006f6ba60Sopenharmony_ci        char buf[bufSize] = { 0 };
6106f6ba60Sopenharmony_ci        strerror_r(errno, buf, bufSize);
6206f6ba60Sopenharmony_ci        PROFILER_LOG_WARN(LOG_CORE, "open file %s FAILED: %s!", path.c_str(), buf);
6306f6ba60Sopenharmony_ci        return "";
6406f6ba60Sopenharmony_ci    }
6506f6ba60Sopenharmony_ci    std::string content = ReadFile(fd);
6606f6ba60Sopenharmony_ci    CHECK_TRUE(close(fd) != -1, content, "close %s failed, %d", path.c_str(), errno);
6706f6ba60Sopenharmony_ci    return content;
6806f6ba60Sopenharmony_ci}
6906f6ba60Sopenharmony_ci
7006f6ba60Sopenharmony_ciint FileUtils::WriteFile(const std::string& path, const std::string& content)
7106f6ba60Sopenharmony_ci{
7206f6ba60Sopenharmony_ci    return WriteFile(path, content, O_WRONLY);
7306f6ba60Sopenharmony_ci}
7406f6ba60Sopenharmony_ci
7506f6ba60Sopenharmony_ciint FileUtils::WriteFile(const std::string& path, const std::string& content, int flags)
7606f6ba60Sopenharmony_ci{
7706f6ba60Sopenharmony_ci    return WriteFile(path, content, flags, 0);
7806f6ba60Sopenharmony_ci}
7906f6ba60Sopenharmony_ci
8006f6ba60Sopenharmony_ciint FileUtils::WriteFile(const std::string& path, const std::string& content, int flags, int mode)
8106f6ba60Sopenharmony_ci{
8206f6ba60Sopenharmony_ci    CHECK_TRUE(!path.empty() && (path.length() < PATH_MAX), -1,
8306f6ba60Sopenharmony_ci               "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
8406f6ba60Sopenharmony_ci
8506f6ba60Sopenharmony_ci    std::regex dirNameRegex("[.~-]");
8606f6ba60Sopenharmony_ci    std::regex fileNameRegex("[\\/:*?\"<>|]");
8706f6ba60Sopenharmony_ci    size_t pos = path.rfind("/");
8806f6ba60Sopenharmony_ci    if (pos != std::string::npos) {
8906f6ba60Sopenharmony_ci        std::string dirName = path.substr(0, pos+1);
9006f6ba60Sopenharmony_ci        size_t index = path.length() > (pos + 1) ? path.length() - pos - 1 : 0;
9106f6ba60Sopenharmony_ci        std::string fileName = path.substr(pos+1, index);
9206f6ba60Sopenharmony_ci        CHECK_TRUE(!(std::regex_search(dirName, dirNameRegex) || std::regex_search(fileName, fileNameRegex)), -1,
9306f6ba60Sopenharmony_ci                   "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
9406f6ba60Sopenharmony_ci    } else {
9506f6ba60Sopenharmony_ci        CHECK_TRUE(!std::regex_search(path, fileNameRegex), -1,
9606f6ba60Sopenharmony_ci                   "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
9706f6ba60Sopenharmony_ci    }
9806f6ba60Sopenharmony_ci
9906f6ba60Sopenharmony_ci    int fd = open(path.c_str(), flags, mode);
10006f6ba60Sopenharmony_ci    CHECK_TRUE(fd >= 0, -1, "open %s failed, %d", path.c_str(), errno);
10106f6ba60Sopenharmony_ci
10206f6ba60Sopenharmony_ci    int retval = write(fd, content.data(), content.size());
10306f6ba60Sopenharmony_ci    CHECK_TRUE(close(fd) != -1, -1, "close %s failed, %d", path.c_str(), errno);
10406f6ba60Sopenharmony_ci    return retval;
10506f6ba60Sopenharmony_ci}
10606f6ba60Sopenharmony_ci
10706f6ba60Sopenharmony_cistd::vector<std::string> FileUtils::ListDir(const std::string& dirPath)
10806f6ba60Sopenharmony_ci{
10906f6ba60Sopenharmony_ci    std::vector<std::string> result;
11006f6ba60Sopenharmony_ci    DIR* dir = opendir(dirPath.c_str());
11106f6ba60Sopenharmony_ci    if (dir == nullptr) {
11206f6ba60Sopenharmony_ci        return result;
11306f6ba60Sopenharmony_ci    }
11406f6ba60Sopenharmony_ci
11506f6ba60Sopenharmony_ci    struct dirent* ent = nullptr;
11606f6ba60Sopenharmony_ci    while ((ent = readdir(dir)) != nullptr) {
11706f6ba60Sopenharmony_ci        std::string name = ent->d_name;
11806f6ba60Sopenharmony_ci        if (name == "." || name == "..") {
11906f6ba60Sopenharmony_ci            continue;
12006f6ba60Sopenharmony_ci        }
12106f6ba60Sopenharmony_ci        result.push_back(name);
12206f6ba60Sopenharmony_ci    }
12306f6ba60Sopenharmony_ci    closedir(dir);
12406f6ba60Sopenharmony_ci    return result;
12506f6ba60Sopenharmony_ci}
126