158ec469eSopenharmony_ci/*
258ec469eSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
358ec469eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
458ec469eSopenharmony_ci * you may not use this file except in compliance with the License.
558ec469eSopenharmony_ci * You may obtain a copy of the License at
658ec469eSopenharmony_ci *
758ec469eSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
858ec469eSopenharmony_ci *
958ec469eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1058ec469eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1158ec469eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1258ec469eSopenharmony_ci * See the License for the specific language governing permissions and
1358ec469eSopenharmony_ci * limitations under the License.
1458ec469eSopenharmony_ci */
1558ec469eSopenharmony_ci#include "file_utils.h"
1658ec469eSopenharmony_ci
1758ec469eSopenharmony_ci#include <cerrno>
1858ec469eSopenharmony_ci#include <cinttypes>
1958ec469eSopenharmony_ci#include <sys/stat.h>
2058ec469eSopenharmony_ci#include <unistd.h>
2158ec469eSopenharmony_ci
2258ec469eSopenharmony_ci#include "securec.h"
2358ec469eSopenharmony_ci#include "sensors_errors.h"
2458ec469eSopenharmony_ci
2558ec469eSopenharmony_ci#undef LOG_TAG
2658ec469eSopenharmony_ci#define LOG_TAG "MiscdeviceFileUtils"
2758ec469eSopenharmony_ci
2858ec469eSopenharmony_cinamespace OHOS {
2958ec469eSopenharmony_cinamespace Sensors {
3058ec469eSopenharmony_cinamespace {
3158ec469eSopenharmony_ciconst std::string CONFIG_DIR = "/vendor/etc/vibrator/";
3258ec469eSopenharmony_ciconstexpr int32_t FILE_SIZE_MAX = 0x5000;
3358ec469eSopenharmony_ciconstexpr int64_t READ_DATA_BUFF_SIZE = 256;
3458ec469eSopenharmony_ciconstexpr int32_t INVALID_FILE_SIZE = -1;
3558ec469eSopenharmony_ciconstexpr int32_t FILE_PATH_MAX = 1024;
3658ec469eSopenharmony_ci} // namespace
3758ec469eSopenharmony_ci
3858ec469eSopenharmony_cistd::string ReadJsonFile(const std::string &filePath)
3958ec469eSopenharmony_ci{
4058ec469eSopenharmony_ci    if (filePath.empty()) {
4158ec469eSopenharmony_ci        MISC_HILOGE("Path is empty");
4258ec469eSopenharmony_ci        return {};
4358ec469eSopenharmony_ci    }
4458ec469eSopenharmony_ci    char realPath[PATH_MAX] = {};
4558ec469eSopenharmony_ci    if (realpath(filePath.c_str(), realPath) == nullptr) {
4658ec469eSopenharmony_ci        MISC_HILOGE("Path is error, %{public}d", errno);
4758ec469eSopenharmony_ci        return {};
4858ec469eSopenharmony_ci    }
4958ec469eSopenharmony_ci    if (!CheckFileDir(realPath, CONFIG_DIR)) {
5058ec469eSopenharmony_ci        MISC_HILOGE("File dir is invalid");
5158ec469eSopenharmony_ci        return {};
5258ec469eSopenharmony_ci    }
5358ec469eSopenharmony_ci    if (!CheckFileExtendName(realPath, "json")) {
5458ec469eSopenharmony_ci        MISC_HILOGE("Unable to parse files other than json format");
5558ec469eSopenharmony_ci        return {};
5658ec469eSopenharmony_ci    }
5758ec469eSopenharmony_ci    if (!IsFileExists(realPath)) {
5858ec469eSopenharmony_ci        MISC_HILOGE("File not exist");
5958ec469eSopenharmony_ci        return {};
6058ec469eSopenharmony_ci    }
6158ec469eSopenharmony_ci    if (!CheckFileSize(realPath)) {
6258ec469eSopenharmony_ci        MISC_HILOGE("File size out of read range");
6358ec469eSopenharmony_ci        return {};
6458ec469eSopenharmony_ci    }
6558ec469eSopenharmony_ci    FILE *fp = fopen(realPath, "r");
6658ec469eSopenharmony_ci    CHKPS(fp);
6758ec469eSopenharmony_ci    std::string dataStr;
6858ec469eSopenharmony_ci    char buf[READ_DATA_BUFF_SIZE] = { '\0' };
6958ec469eSopenharmony_ci    while (fgets(buf, sizeof(buf), fp) != nullptr) {
7058ec469eSopenharmony_ci        dataStr += buf;
7158ec469eSopenharmony_ci    }
7258ec469eSopenharmony_ci    if (fclose(fp) != 0) {
7358ec469eSopenharmony_ci        MISC_HILOGW("Close file failed, errno:%{public}d", errno);
7458ec469eSopenharmony_ci    }
7558ec469eSopenharmony_ci    return dataStr;
7658ec469eSopenharmony_ci}
7758ec469eSopenharmony_ci
7858ec469eSopenharmony_ciint32_t GetFileSize(const std::string &filePath)
7958ec469eSopenharmony_ci{
8058ec469eSopenharmony_ci    struct stat statbuf = { 0 };
8158ec469eSopenharmony_ci    if (stat(filePath.c_str(), &statbuf) != 0) {
8258ec469eSopenharmony_ci        MISC_HILOGE("Get file size error");
8358ec469eSopenharmony_ci        return INVALID_FILE_SIZE;
8458ec469eSopenharmony_ci    }
8558ec469eSopenharmony_ci    return statbuf.st_size;
8658ec469eSopenharmony_ci}
8758ec469eSopenharmony_ci
8858ec469eSopenharmony_ciint64_t GetFileSize(int32_t fd)
8958ec469eSopenharmony_ci{
9058ec469eSopenharmony_ci    if (fd < 0) {
9158ec469eSopenharmony_ci        MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
9258ec469eSopenharmony_ci        return INVALID_FILE_SIZE;
9358ec469eSopenharmony_ci    }
9458ec469eSopenharmony_ci    struct stat64 statbuf = { 0 };
9558ec469eSopenharmony_ci    if (fstat64(fd, &statbuf) != 0) {
9658ec469eSopenharmony_ci        MISC_HILOGE("fstat error, errno:%{public}d", errno);
9758ec469eSopenharmony_ci        return INVALID_FILE_SIZE;
9858ec469eSopenharmony_ci    }
9958ec469eSopenharmony_ci    return statbuf.st_size;
10058ec469eSopenharmony_ci}
10158ec469eSopenharmony_ci
10258ec469eSopenharmony_ciint32_t GetFileName(const int32_t &fd, std::string &fileName)
10358ec469eSopenharmony_ci{
10458ec469eSopenharmony_ci    if (fd < 0) {
10558ec469eSopenharmony_ci        MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
10658ec469eSopenharmony_ci        return ERROR;
10758ec469eSopenharmony_ci    }
10858ec469eSopenharmony_ci    char buf[FILE_PATH_MAX] = {'\0'};
10958ec469eSopenharmony_ci    char filePath[FILE_PATH_MAX] = {'\0'};
11058ec469eSopenharmony_ci
11158ec469eSopenharmony_ci    int ret = snprintf_s(buf, sizeof(buf), (sizeof(buf) - 1), "/proc/self/fd/%d", fd);
11258ec469eSopenharmony_ci    if (ret < 0) {
11358ec469eSopenharmony_ci        MISC_HILOGE("snprintf failed with %{public}d", errno);
11458ec469eSopenharmony_ci        return ERROR;
11558ec469eSopenharmony_ci    }
11658ec469eSopenharmony_ci
11758ec469eSopenharmony_ci    ret = readlink(buf, filePath, FILE_PATH_MAX);
11858ec469eSopenharmony_ci    if (ret < 0 || ret >= FILE_PATH_MAX) {
11958ec469eSopenharmony_ci        MISC_HILOGE("readlink failed with %{public}d", errno);
12058ec469eSopenharmony_ci        return ERROR;
12158ec469eSopenharmony_ci    }
12258ec469eSopenharmony_ci
12358ec469eSopenharmony_ci    fileName = filePath;
12458ec469eSopenharmony_ci    std::size_t firstSlash = fileName.rfind("/");
12558ec469eSopenharmony_ci    if (firstSlash == fileName.npos) {
12658ec469eSopenharmony_ci        MISC_HILOGE("Get error path");
12758ec469eSopenharmony_ci        return ERROR;
12858ec469eSopenharmony_ci    }
12958ec469eSopenharmony_ci    fileName = fileName.substr(firstSlash + 1, fileName.size() - firstSlash);
13058ec469eSopenharmony_ci    return SUCCESS;
13158ec469eSopenharmony_ci}
13258ec469eSopenharmony_ci
13358ec469eSopenharmony_ciint32_t GetFileExtName(const int32_t &fd, std::string &extName)
13458ec469eSopenharmony_ci{
13558ec469eSopenharmony_ci    if (fd < 0) {
13658ec469eSopenharmony_ci        MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
13758ec469eSopenharmony_ci        return ERROR;
13858ec469eSopenharmony_ci    }
13958ec469eSopenharmony_ci    std::string fileName = "";
14058ec469eSopenharmony_ci    if (GetFileName(fd, fileName) == ERROR) {
14158ec469eSopenharmony_ci        MISC_HILOGE("GetFileName failed");
14258ec469eSopenharmony_ci        return ERROR;
14358ec469eSopenharmony_ci    }
14458ec469eSopenharmony_ci    extName = fileName.substr(fileName.find_last_of(".") + 1);
14558ec469eSopenharmony_ci    return SUCCESS;
14658ec469eSopenharmony_ci}
14758ec469eSopenharmony_ci
14858ec469eSopenharmony_cibool CheckFileDir(const std::string &filePath, const std::string &dir)
14958ec469eSopenharmony_ci{
15058ec469eSopenharmony_ci    if (filePath.compare(0, CONFIG_DIR.size(), CONFIG_DIR) != 0) {
15158ec469eSopenharmony_ci        MISC_HILOGE("filePath dir is invalid");
15258ec469eSopenharmony_ci        return false;
15358ec469eSopenharmony_ci    }
15458ec469eSopenharmony_ci    return true;
15558ec469eSopenharmony_ci}
15658ec469eSopenharmony_ci
15758ec469eSopenharmony_cibool CheckFileSize(const std::string &filePath)
15858ec469eSopenharmony_ci{
15958ec469eSopenharmony_ci    int32_t fileSize = GetFileSize(filePath);
16058ec469eSopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
16158ec469eSopenharmony_ci        MISC_HILOGE("File size out of read range");
16258ec469eSopenharmony_ci        return false;
16358ec469eSopenharmony_ci    }
16458ec469eSopenharmony_ci    return true;
16558ec469eSopenharmony_ci}
16658ec469eSopenharmony_ci
16758ec469eSopenharmony_cibool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
16858ec469eSopenharmony_ci{
16958ec469eSopenharmony_ci    std::string::size_type pos = filePath.find_last_of('.');
17058ec469eSopenharmony_ci    if (pos == std::string::npos) {
17158ec469eSopenharmony_ci        MISC_HILOGE("File is not find extension");
17258ec469eSopenharmony_ci        return false;
17358ec469eSopenharmony_ci    }
17458ec469eSopenharmony_ci    return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
17558ec469eSopenharmony_ci}
17658ec469eSopenharmony_ci
17758ec469eSopenharmony_cibool IsFileExists(const std::string &fileName)
17858ec469eSopenharmony_ci{
17958ec469eSopenharmony_ci    return (access(fileName.c_str(), F_OK) == 0);
18058ec469eSopenharmony_ci}
18158ec469eSopenharmony_ci
18258ec469eSopenharmony_cistd::string ReadFd(const RawFileDescriptor &rawFd)
18358ec469eSopenharmony_ci{
18458ec469eSopenharmony_ci    if (rawFd.fd < 0) {
18558ec469eSopenharmony_ci        MISC_HILOGE("fd is invalid, fd:%{public}d", rawFd.fd);
18658ec469eSopenharmony_ci        return {};
18758ec469eSopenharmony_ci    }
18858ec469eSopenharmony_ci    int64_t fdSize = GetFileSize(rawFd.fd);
18958ec469eSopenharmony_ci    if ((rawFd.offset < 0) || (rawFd.offset > fdSize)) {
19058ec469eSopenharmony_ci        MISC_HILOGE("offset is invalid, offset:%{public}" PRId64, rawFd.offset);
19158ec469eSopenharmony_ci        return {};
19258ec469eSopenharmony_ci    }
19358ec469eSopenharmony_ci    if ((rawFd.length <= 0) || (rawFd.length > fdSize - rawFd.offset)) {
19458ec469eSopenharmony_ci        MISC_HILOGE("length is invalid, length:%{public}" PRId64, rawFd.length);
19558ec469eSopenharmony_ci        return {};
19658ec469eSopenharmony_ci    }
19758ec469eSopenharmony_ci    FILE *fp = fdopen(rawFd.fd, "r");
19858ec469eSopenharmony_ci    CHKPS(fp);
19958ec469eSopenharmony_ci    if (fseek(fp, rawFd.offset, SEEK_SET) != 0) {
20058ec469eSopenharmony_ci        MISC_HILOGE("fseek failed, errno:%{public}d", errno);
20158ec469eSopenharmony_ci        if (fclose(fp) != 0) {
20258ec469eSopenharmony_ci            MISC_HILOGW("Close file failed, errno:%{public}d", errno);
20358ec469eSopenharmony_ci        }
20458ec469eSopenharmony_ci        return {};
20558ec469eSopenharmony_ci    }
20658ec469eSopenharmony_ci    std::string dataStr;
20758ec469eSopenharmony_ci    char buf[READ_DATA_BUFF_SIZE] = { '\0' };
20858ec469eSopenharmony_ci    int64_t alreadyRead = 0;
20958ec469eSopenharmony_ci    while (alreadyRead < rawFd.length) {
21058ec469eSopenharmony_ci        int64_t onceRead = std::min(rawFd.length - alreadyRead, READ_DATA_BUFF_SIZE - 1);
21158ec469eSopenharmony_ci        fgets(buf, onceRead + 1, fp);
21258ec469eSopenharmony_ci        dataStr += buf;
21358ec469eSopenharmony_ci        alreadyRead = ftell(fp) - rawFd.offset;
21458ec469eSopenharmony_ci    }
21558ec469eSopenharmony_ci    if (fclose(fp) != 0) {
21658ec469eSopenharmony_ci        MISC_HILOGW("Close file failed, errno:%{public}d", errno);
21758ec469eSopenharmony_ci    }
21858ec469eSopenharmony_ci    return dataStr;
21958ec469eSopenharmony_ci}
22058ec469eSopenharmony_ci
22158ec469eSopenharmony_cistd::string GetFileSuffix(int32_t fd)
22258ec469eSopenharmony_ci{
22358ec469eSopenharmony_ci    std::string fdPath = "/proc/self/fd/" + std::to_string(fd);
22458ec469eSopenharmony_ci    char filePath[FILE_PATH_MAX + 1] = { '\0' };
22558ec469eSopenharmony_ci    ssize_t ret = readlink(fdPath.c_str(), filePath, FILE_PATH_MAX);
22658ec469eSopenharmony_ci    if (ret < 0 || ret > FILE_PATH_MAX) {
22758ec469eSopenharmony_ci        MISC_HILOGE("Readlink failed, errno:%{public}d", errno);
22858ec469eSopenharmony_ci        return {};
22958ec469eSopenharmony_ci    }
23058ec469eSopenharmony_ci    std::string fileAbsolutePath(filePath);
23158ec469eSopenharmony_ci    size_t pos = fileAbsolutePath.find_last_of('.');
23258ec469eSopenharmony_ci    if (pos == std::string::npos) {
23358ec469eSopenharmony_ci        MISC_HILOGE("File suffix is invalid, fileAbsolutePath:%{public}s", fileAbsolutePath.c_str());
23458ec469eSopenharmony_ci        return {};
23558ec469eSopenharmony_ci    }
23658ec469eSopenharmony_ci    return fileAbsolutePath.substr(pos + 1);
23758ec469eSopenharmony_ci}
23858ec469eSopenharmony_ci} // namespace Sensors
23958ec469eSopenharmony_ci} // namespace OHOS
240