1/* 2 * Copyright (c) 2022-2023 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#include "file_utils.h" 16 17#include <cerrno> 18#include <cinttypes> 19#include <sys/stat.h> 20#include <unistd.h> 21 22#include "securec.h" 23#include "sensors_errors.h" 24 25#undef LOG_TAG 26#define LOG_TAG "MiscdeviceFileUtils" 27 28namespace OHOS { 29namespace Sensors { 30namespace { 31const std::string CONFIG_DIR = "/vendor/etc/vibrator/"; 32constexpr int32_t FILE_SIZE_MAX = 0x5000; 33constexpr int64_t READ_DATA_BUFF_SIZE = 256; 34constexpr int32_t INVALID_FILE_SIZE = -1; 35constexpr int32_t FILE_PATH_MAX = 1024; 36} // namespace 37 38std::string ReadJsonFile(const std::string &filePath) 39{ 40 if (filePath.empty()) { 41 MISC_HILOGE("Path is empty"); 42 return {}; 43 } 44 char realPath[PATH_MAX] = {}; 45 if (realpath(filePath.c_str(), realPath) == nullptr) { 46 MISC_HILOGE("Path is error, %{public}d", errno); 47 return {}; 48 } 49 if (!CheckFileDir(realPath, CONFIG_DIR)) { 50 MISC_HILOGE("File dir is invalid"); 51 return {}; 52 } 53 if (!CheckFileExtendName(realPath, "json")) { 54 MISC_HILOGE("Unable to parse files other than json format"); 55 return {}; 56 } 57 if (!IsFileExists(realPath)) { 58 MISC_HILOGE("File not exist"); 59 return {}; 60 } 61 if (!CheckFileSize(realPath)) { 62 MISC_HILOGE("File size out of read range"); 63 return {}; 64 } 65 FILE *fp = fopen(realPath, "r"); 66 CHKPS(fp); 67 std::string dataStr; 68 char buf[READ_DATA_BUFF_SIZE] = { '\0' }; 69 while (fgets(buf, sizeof(buf), fp) != nullptr) { 70 dataStr += buf; 71 } 72 if (fclose(fp) != 0) { 73 MISC_HILOGW("Close file failed, errno:%{public}d", errno); 74 } 75 return dataStr; 76} 77 78int32_t GetFileSize(const std::string &filePath) 79{ 80 struct stat statbuf = { 0 }; 81 if (stat(filePath.c_str(), &statbuf) != 0) { 82 MISC_HILOGE("Get file size error"); 83 return INVALID_FILE_SIZE; 84 } 85 return statbuf.st_size; 86} 87 88int64_t GetFileSize(int32_t fd) 89{ 90 if (fd < 0) { 91 MISC_HILOGE("fd is invalid, fd:%{public}d", fd); 92 return INVALID_FILE_SIZE; 93 } 94 struct stat64 statbuf = { 0 }; 95 if (fstat64(fd, &statbuf) != 0) { 96 MISC_HILOGE("fstat error, errno:%{public}d", errno); 97 return INVALID_FILE_SIZE; 98 } 99 return statbuf.st_size; 100} 101 102int32_t GetFileName(const int32_t &fd, std::string &fileName) 103{ 104 if (fd < 0) { 105 MISC_HILOGE("fd is invalid, fd:%{public}d", fd); 106 return ERROR; 107 } 108 char buf[FILE_PATH_MAX] = {'\0'}; 109 char filePath[FILE_PATH_MAX] = {'\0'}; 110 111 int ret = snprintf_s(buf, sizeof(buf), (sizeof(buf) - 1), "/proc/self/fd/%d", fd); 112 if (ret < 0) { 113 MISC_HILOGE("snprintf failed with %{public}d", errno); 114 return ERROR; 115 } 116 117 ret = readlink(buf, filePath, FILE_PATH_MAX); 118 if (ret < 0 || ret >= FILE_PATH_MAX) { 119 MISC_HILOGE("readlink failed with %{public}d", errno); 120 return ERROR; 121 } 122 123 fileName = filePath; 124 std::size_t firstSlash = fileName.rfind("/"); 125 if (firstSlash == fileName.npos) { 126 MISC_HILOGE("Get error path"); 127 return ERROR; 128 } 129 fileName = fileName.substr(firstSlash + 1, fileName.size() - firstSlash); 130 return SUCCESS; 131} 132 133int32_t GetFileExtName(const int32_t &fd, std::string &extName) 134{ 135 if (fd < 0) { 136 MISC_HILOGE("fd is invalid, fd:%{public}d", fd); 137 return ERROR; 138 } 139 std::string fileName = ""; 140 if (GetFileName(fd, fileName) == ERROR) { 141 MISC_HILOGE("GetFileName failed"); 142 return ERROR; 143 } 144 extName = fileName.substr(fileName.find_last_of(".") + 1); 145 return SUCCESS; 146} 147 148bool CheckFileDir(const std::string &filePath, const std::string &dir) 149{ 150 if (filePath.compare(0, CONFIG_DIR.size(), CONFIG_DIR) != 0) { 151 MISC_HILOGE("filePath dir is invalid"); 152 return false; 153 } 154 return true; 155} 156 157bool CheckFileSize(const std::string &filePath) 158{ 159 int32_t fileSize = GetFileSize(filePath); 160 if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) { 161 MISC_HILOGE("File size out of read range"); 162 return false; 163 } 164 return true; 165} 166 167bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension) 168{ 169 std::string::size_type pos = filePath.find_last_of('.'); 170 if (pos == std::string::npos) { 171 MISC_HILOGE("File is not find extension"); 172 return false; 173 } 174 return (filePath.substr(pos + 1, filePath.npos) == checkExtension); 175} 176 177bool IsFileExists(const std::string &fileName) 178{ 179 return (access(fileName.c_str(), F_OK) == 0); 180} 181 182std::string ReadFd(const RawFileDescriptor &rawFd) 183{ 184 if (rawFd.fd < 0) { 185 MISC_HILOGE("fd is invalid, fd:%{public}d", rawFd.fd); 186 return {}; 187 } 188 int64_t fdSize = GetFileSize(rawFd.fd); 189 if ((rawFd.offset < 0) || (rawFd.offset > fdSize)) { 190 MISC_HILOGE("offset is invalid, offset:%{public}" PRId64, rawFd.offset); 191 return {}; 192 } 193 if ((rawFd.length <= 0) || (rawFd.length > fdSize - rawFd.offset)) { 194 MISC_HILOGE("length is invalid, length:%{public}" PRId64, rawFd.length); 195 return {}; 196 } 197 FILE *fp = fdopen(rawFd.fd, "r"); 198 CHKPS(fp); 199 if (fseek(fp, rawFd.offset, SEEK_SET) != 0) { 200 MISC_HILOGE("fseek failed, errno:%{public}d", errno); 201 if (fclose(fp) != 0) { 202 MISC_HILOGW("Close file failed, errno:%{public}d", errno); 203 } 204 return {}; 205 } 206 std::string dataStr; 207 char buf[READ_DATA_BUFF_SIZE] = { '\0' }; 208 int64_t alreadyRead = 0; 209 while (alreadyRead < rawFd.length) { 210 int64_t onceRead = std::min(rawFd.length - alreadyRead, READ_DATA_BUFF_SIZE - 1); 211 fgets(buf, onceRead + 1, fp); 212 dataStr += buf; 213 alreadyRead = ftell(fp) - rawFd.offset; 214 } 215 if (fclose(fp) != 0) { 216 MISC_HILOGW("Close file failed, errno:%{public}d", errno); 217 } 218 return dataStr; 219} 220 221std::string GetFileSuffix(int32_t fd) 222{ 223 std::string fdPath = "/proc/self/fd/" + std::to_string(fd); 224 char filePath[FILE_PATH_MAX + 1] = { '\0' }; 225 ssize_t ret = readlink(fdPath.c_str(), filePath, FILE_PATH_MAX); 226 if (ret < 0 || ret > FILE_PATH_MAX) { 227 MISC_HILOGE("Readlink failed, errno:%{public}d", errno); 228 return {}; 229 } 230 std::string fileAbsolutePath(filePath); 231 size_t pos = fileAbsolutePath.find_last_of('.'); 232 if (pos == std::string::npos) { 233 MISC_HILOGE("File suffix is invalid, fileAbsolutePath:%{public}s", fileAbsolutePath.c_str()); 234 return {}; 235 } 236 return fileAbsolutePath.substr(pos + 1); 237} 238} // namespace Sensors 239} // namespace OHOS 240